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.

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

html
<!-- 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

javascript
<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:

tsx
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:

secondaryPhone, address, city, region, country, placeOfBirthTown, placeOfBirthRegion, placeOfBirthCountry, occupation, employer

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.

http
POST /api/v1/extract HTTP/1.1
Host: mrz-portal.vercel.app
x-api-key: YOUR_API_KEY
Content-Type: application/json

Extraction Endpoint

The primary endpoint for processing document images.

POST/api/v1/extract
  • 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.
Billing note: credit-based organizations are charged only for successful scans that meet the minimum confidence threshold (default 90%, configurable). SLA organizations require an active subscription.

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)

json
{
  "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)

bash
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.

json
{
  "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"
}
The MRZ engine may return additional fields (e.g., mrz_text, mrz_type, image_quality). Treat unknown fields as optional. Confidence may be returned as a 0-1 or 0-100 score depending on the engine.

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.

POST/api/verifications/save

Stores the verification record, images, and additional profile data.

json
{
  "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"
}
Additional optional fields: city, region, country,place_of_birth_town, place_of_birth_region, place_of_birth_country,occupation, employer.
POST/api/verifications/link

Fast-track verification by linking to an existing individual using their document number.

json
{
  "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.

json
{
  "success": false,
  "error": "Insufficient credits",
  "code": "INSUFFICIENT_CREDITS"
}
400 Invalid payload or missing file/image.
401 Missing or invalid API key.
402 Billing blocked (INSUFFICIENT_CREDITS, SLA_EXPIRED).
403 Organization not approved.
410 Widget session expired or already completed.
429 Rate limit or server busy (check Retry-After header).
502 Upstream MRZ engine returned an invalid response.

Code Examples

JSJavaScript (Fetch)

javascript
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));

cURLcURL

bash
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"

PythonPython

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