Basic Integration Guide
A comprehensive guide to integrating MIMS SDK into your React application from start to finish.
Prerequisites
Before starting, ensure you have completed the installation and have your API key ready.
Integration Overview
This guide walks you through building a complete document signing flow with the following features:
- Loading documents from your backend
- Displaying the PDF with form fields
- Capturing signatures
- Submitting completed documents
- Handling success and error states
Step 1: Set Up the Provider
Create a providers file that wraps your application with the MIMS provider:
app/providers.tsxtypescript
1'use client';23import { MIMSProvider } from '@mims/sdk-react';4import { ReactNode, useState, useEffect } from 'react';56export function Providers({ children }: { children: ReactNode }) {7 const [mounted, setMounted] = useState(false);89 // Avoid hydration mismatch10 useEffect(() => {11 setMounted(true);12 }, []);1314 if (!mounted) {15 return null;16 }1718 return (19 <MIMSProvider20 apiKey={process.env.NEXT_PUBLIC_MIMS_API_KEY!}21 debug={process.env.NODE_ENV === 'development'}22 onReady={() => {23 console.log('MIMS SDK ready');24 }}25 onError={(error) => {26 console.error('MIMS SDK error:', error);27 }}28 >29 {children}30 </MIMSProvider>31 );32}Step 2: Create the Document Service
Create a service to fetch document details from your backend:
lib/documents.tstypescript
export interface Document {
id: string;
title: string;
url: string;
fields: FieldDefinition[];
status: 'draft' | 'pending' | 'completed';
}
export async function getDocument(documentId: string): Promise<Document> {
const response = await fetch(`/api/documents/${documentId}`);
if (!response.ok) {
throw new Error('Failed to fetch document');
}
return response.json();
}
export async function completeDocument(
documentId: string,
submissionData: {
submittedAt: string;
checksum: string;
}
): Promise<void> {
const response = await fetch(`/api/documents/${documentId}/complete`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(submissionData),
});
if (!response.ok) {
throw new Error('Failed to complete document');
}
}Step 3: Build the Document Viewer Component
components/document-viewer.tsxtypescript
1'use client';23import { useState, useEffect } from 'react';4import { PDFViewer, useSDK, type DocumentSubmissionPayload } from '@mims/sdk-react';5import { getDocument, completeDocument, type Document } from '@/lib/documents';67interface DocumentViewerProps {8 documentId: string;9 onComplete?: () => void;10}1112export function DocumentViewer({ documentId, onComplete }: DocumentViewerProps) {13 const { isInitialized, validationError } = useSDK();14 const [document, setDocument] = useState<Document | null>(null);15 const [loading, setLoading] = useState(true);16 const [error, setError] = useState<string | null>(null);17 const [submitted, setSubmitted] = useState(false);1819 // Fetch document on mount20 useEffect(() => {21 if (!isInitialized) return;2223 async function fetchDocument() {24 try {25 const doc = await getDocument(documentId);26 setDocument(doc);27 } catch (err) {28 setError(err instanceof Error ? err.message : 'Failed to load document');29 } finally {30 setLoading(false);31 }32 }3334 fetchDocument();35 }, [documentId, isInitialized]);3637 // Handle submission38 const handleSubmit = async (payload: DocumentSubmissionPayload) => {39 try {40 // Notify your backend41 await completeDocument(documentId, {42 submittedAt: payload.submittedAt,43 checksum: payload.checksum,44 });45 46 setSubmitted(true);47 onComplete?.();48 } catch (err) {49 throw err; // Let the SDK handle the error display50 }51 };5253 // Loading state54 if (loading || !isInitialized) {55 return (56 <div className="flex items-center justify-center h-96">57 <div className="animate-spin h-8 w-8 border-4 border-blue-500 border-t-transparent rounded-full" />58 </div>59 );60 }6162 // Error state63 if (error || validationError) {64 return (65 <div className="bg-red-50 border border-red-200 rounded-lg p-6 text-center">66 <h3 className="text-red-800 font-semibold">Error Loading Document</h3>67 <p className="text-red-600 mt-2">{error || validationError}</p>68 <button69 onClick={() => window.location.reload()}70 className="mt-4 px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700"71 >72 Try Again73 </button>74 </div>75 );76 }7778 // Success state79 if (submitted) {80 return (81 <div className="bg-green-50 border border-green-200 rounded-lg p-6 text-center">82 <div className="text-green-500 text-5xl mb-4">✓</div>83 <h3 className="text-green-800 font-semibold text-xl">84 Document Submitted Successfully!85 </h3>86 <p className="text-green-600 mt-2">87 Your signed document has been processed and saved.88 </p>89 </div>90 );91 }9293 // Render viewer94 if (!document) return null;9596 return (97 <div className="h-[80vh] border rounded-lg overflow-hidden">98 <PDFViewer99 documentId={document.id}100 documentUrl={document.url}101 initialFields={document.fields}102 onSubmit={handleSubmit}103 onSubmitError={(err) => {104 setError(err.message);105 }}106 />107 </div>108 );109}Step 4: Create the Page
app/documents/[id]/page.tsxtypescript
import { DocumentViewer } from '@/components/document-viewer';
import { Suspense } from 'react';
interface DocumentPageProps {
params: { id: string };
}
export default function DocumentPage({ params }: DocumentPageProps) {
return (
<div className="container mx-auto py-8 px-4">
<header className="mb-6">
<h1 className="text-2xl font-bold">Review & Sign Document</h1>
<p className="text-gray-600 mt-1">
Please review the document and fill in all required fields.
</p>
</header>
<Suspense fallback={<DocumentSkeleton />}>
<DocumentViewer
documentId={params.id}
onComplete={() => {
// Navigate to success page or show notification
console.log('Document completed!');
}}
/>
</Suspense>
</div>
);
}
function DocumentSkeleton() {
return (
<div className="h-[80vh] border rounded-lg bg-gray-100 animate-pulse" />
);
}Step 5: Create the API Routes
app/api/documents/[id]/route.tstypescript
import { NextResponse } from 'next/server';
export async function GET(
request: Request,
{ params }: { params: { id: string } }
) {
// Fetch document from your database
const document = await prisma.document.findUnique({
where: { id: params.id },
include: { fields: true },
});
if (!document) {
return NextResponse.json(
{ error: 'Document not found' },
{ status: 404 }
);
}
// Generate signed URL for PDF
const url = await generateSignedUrl(document.s3Key);
return NextResponse.json({
id: document.id,
title: document.title,
url,
fields: document.fields,
status: document.status,
});
}app/api/documents/[id]/complete/route.tstypescript
import { NextResponse } from 'next/server';
export async function POST(
request: Request,
{ params }: { params: { id: string } }
) {
const body = await request.json();
// Update document status
await prisma.document.update({
where: { id: params.id },
data: {
status: 'completed',
completedAt: new Date(body.submittedAt),
checksum: body.checksum,
},
});
// Trigger any post-completion workflows
await sendCompletionNotification(params.id);
return NextResponse.json({ success: true });
}Complete Flow Diagram
┌─────────────────────────────────────────────────────────────┐
│ User Flow │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 1. User navigates to /documents/[id] │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 2. MIMSProvider validates API key │
│ POST /sdk/validate-key │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 3. DocumentViewer fetches document details │
│ GET /api/documents/[id] │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 4. PDFViewer loads and renders PDF │
│ - Displays form fields │
│ - User fills fields and signs │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 5. User clicks Submit │
│ - SDK validates all required fields │
│ - SDK sends submission to MIMS API │
│ POST /sdk/documents/submit │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 6. Your backend is notified │
│ POST /api/documents/[id]/complete │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 7. Success! Document is completed │
└─────────────────────────────────────────────────────────────┘Next Steps
Now that you have a basic integration working, explore these advanced topics: