API Documentation
Integrate Ghana Card, passport, and visa verification directly into your applications. Use the widget for the fastest launch, or call the API to extract MRZ data and store verification records.
On this page
Easiest Integration: JavaScript Widget
The fastest way to add ID verification to any website. Works with React, Vue, Angular, or plain HTML.
Step 1: Add the script tag
<!-- If hosting yourself -->
<script src="/trueid-widget.js"></script>
<!-- Or use hosted script from TrueID -->
<script src="https://mrz-portal.vercel.app/trueid-widget.js"></script>Step 2: Initialize with your API key
<button id="verify-btn">Verify ID</button>
<script>
TrueIDWidget.init({
apiKey: 'YOUR_API_KEY',
buttonSelector: '#verify-btn',
// Optional: defaults can also be managed in Settings → Widget Customization
documentType: 'auto', // 'ghana_card' | 'ghana_passport' | 'international_passport' | 'international_id' | 'visa'
theme: 'auto', // 'light' | 'dark' | 'auto'
collectAdditionalInfo: true,
showResultReview: true,
autoCapture: true,
// Optional branding
primaryColor: '#1e40af',
accentColor: '#22c55e',
termsUrl: 'https://yourdomain.com/terms',
// Optional: Point to custom API/models if not hosting on TrueID domain
apiEndpoint: 'https://mrz-portal.vercel.app/api/v1/extract',
modelsBaseUrl: 'https://mrz-portal.vercel.app/models',
onSuccess: (data) => {
console.log('Verification successful:', data);
alert(`Verified: ${data.given_names} ${data.surname}`);
},
onError: (error) => {
console.error('Verification failed:', error);
},
onClose: () => {
console.log('Widget closed');
}
});
</script>Widget defaults in Settings
Admins can set default theme, document type, auto-capture, additional fields, colors, and terms URL in Settings → Widget Customization. You can still override them per integration with the config above.
Important: Cross-domain integration
When embedding the widget on your own website (a different domain), you must set both apiEndpoint and modelsBaseUrl to the TrueID server URL. Without these, verification data will not be saved to your organization account. These are only optional when the widget runs on the same domain as the TrueID server.
Try it live!
Visit the Widget Demo Page to see it in action
React / Next.js Integration
Use our React wrapper component for a seamless integration:
import { TrueIDWidget } from '@/components/TrueIDWidget';
function MyComponent() {
return (
<TrueIDWidget
config={{
apiKey: 'YOUR_API_KEY',
// Optional: override remote settings if needed
// apiEndpoint: '...',
onSuccess: (data) => console.log('Verified:', data),
onError: (err) => console.error(err)
}}
>
{(open) => (
<button onClick={open} className="btn-primary">
Verify ID Card
</button>
)}
</TrueIDWidget>
);
}Widget Configuration
The widget loads organization defaults from /api/v1/widget-settings. Any options passed to TrueIDWidget.init() override those defaults.
Required
apiKey
Organization API key used by the widget and API calls.
Trigger
buttonSelector / autoOpen
Attach to a button or auto-open on page load.
Document type
documentType
Guide extraction: auto, ghana_card, ghana_passport,international_passport, international_id, visa.
Theme
theme
Choose light, dark, or auto.
Flow controls
collectAdditionalInfo / showResultReview / autoCapture
Toggle additional info, review step, and auto-capture.
Branding & legal
primaryColor / accentColor / termsUrl
Customize colors and provide a terms/privacy link.
Callbacks
onSuccess / onError / onClose
React to completion, errors, or manual close.
Cross-domain
apiEndpoint / modelsBaseUrl
Set absolute URLs when embedding on another domain.
Additional profile fields
Enable extra fields by passing additionalFields (or set in Widget Customization). Supported keys:
Phone handoff included
The widget can hand off to a phone via QR code when needed. This uses secure widget sessions automatically - no extra setup required.
Authentication
All API requests must be authenticated using your Organization API Key. Include the key in the HTTP header of your requests (extract, verification save/link, and widget sessions).
Keep your key secure
For direct API integrations, keep your API key server-side. The hosted widget uses the key in the browser, so treat it as a widget key and rotate it if it becomes exposed.
POST /api/v1/extract HTTP/1.1
Host: mrz-portal.vercel.app
x-api-key: YOUR_API_KEY
Content-Type: application/jsonExtraction Endpoint
The primary endpoint for processing document images.
- Accepts application/json (base64 image) or multipart/form-data (file upload).
- Optional document_type guides classification; omit or set to auto to auto-detect.
- Returns MRZ data and confidence from the upstream engine.
Request Formats
Send either JSON (base64 data URL) or multipart form-data (file upload). You can optionally specifydocument_type to guide classification.
JSON (base64 data URL)
{
"image": "data:image/jpeg;base64,/9j/4AAQSkZJRg...",
"document_type": "auto" // Optional. Supported: 'ghana_card', 'ghana_passport', 'international_passport', 'international_id', 'visa', 'auto'
}The image must be a full data URL (data:image/...;base64,...).
Multipart form-data (file upload)
curl -X POST https://mrz-portal.vercel.app/api/v1/extract \
-H "x-api-key: YOUR_API_KEY" \
-F "file=@/path/to/card.jpg" \
-F "document_type=ghana_card"Response Structure
The API returns a JSON object with the extracted data and status. The document_type field reflects the resolved classification (e.g., Ghana National ID (TD1), Ghana Passport (TD3), or MRZ codes like ID/P). Ghana Card scans include a pin.
{
"success": true,
"message": "MRZ data extracted successfully",
"data": {
"document_type": "Ghana National ID (TD1)",
"status": "SUCCESS",
"country_code": "GHA",
"nationality": "Ghana",
"issuing_state": "GHA",
"document_code": "ID",
"document_number": "GHA-729485163",
"pin": "GHA-712429053-1",
"birth_date": "1988-03-15",
"age": 37,
"gender": "F",
"expiry_date": "2031-08-22",
"surname": "MENSAH",
"given_names": "ABENA SERWAA",
"full_name": "ABENA SERWAA MENSAH",
"confidence": 0.97,
"document_number_checksum_valid": true,
"birth_date_checksum_valid": true,
"expiry_date_checksum_valid": true,
"cross_validation_warnings": []
},
"processing_time_ms": 842,
"timestamp": "2026-01-28T14:32:18.527341"
}Verification Save & Linking
The widget automatically saves completed verifications. If you call the extract API directly, you can persist results to the portal using the endpoints below.
Stores the verification record, images, and additional profile data.
{
"document_number": "GHA-729485163",
"surname": "MENSAH",
"given_names": "ABENA SERWAA",
"nationality": "Ghana",
"birth_date": "1988-03-15",
"expiry_date": "2031-08-22",
"sex": "F",
"confidence": 0.97,
"raw_data": { "document_type": "Ghana National ID (TD1)", "...": "..." },
"phone": "+233201234567",
"email": "abena@example.com",
"ghana_card_pin": "GHA-712429053-1",
"selfie": "data:image/jpeg;base64,...",
"card_image": "data:image/jpeg;base64,...",
"card_front_image": "data:image/jpeg;base64,...",
"secondary_phone": "0201234567",
"address": "1 Independence Ave"
}Fast-track verification by linking to an existing individual using their document number.
{
"document_number": "GHA-729485163",
"linked_from_organization_id": "ORG_UUID_OPTIONAL"
}Error Handling
Errors are returned as JSON with success: false and a human-readableerror message. Some errors include a code.
{
"success": false,
"error": "Insufficient credits",
"code": "INSUFFICIENT_CREDITS"
}Code Examples
JavaScript (Fetch)
const apiKey = 'YOUR_API_KEY';
const imageBase64 = 'data:image/jpeg;base64,...';
const payload = {
image: imageBase64,
document_type: 'auto'
};
fetch('/api/v1/extract', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey
},
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
cURL
curl -X POST https://mrz-portal.vercel.app/api/v1/extract \
-H "x-api-key: YOUR_API_KEY" \
-F "file=@/path/to/card.jpg" \
-F "document_type=ghana_card"
Python
import requests
url = "https://mrz-portal.vercel.app/api/v1/extract"
headers = {"x-api-key": "YOUR_API_KEY"}
files = {"file": open("card.jpg", "rb")}
data = {"document_type": "auto"}
response = requests.post(url, headers=headers, files=files, data=data)
print(response.json())Need help? Contact Support