Skip to main content

Migrating Onfido Medium to Trust ID M1A

All Onfido endpoints, including Medium and High, are deprecated but remain operational for existing integrations. Trust ID replaces new Digital Identity Medium integrations with a hosted Digital Right to Work M1A flow; it is not a like-for-like replacement for Onfido High. Contact support to plan High migration. The public Medium check code remains digital-identity-medium; the supplier is Trust ID. M1A does not capture address data.

Routes and coexistence​

OperationOnfido Medium / HighTrust ID M1A
CreatePOST /digital-identity-medium; POST /digital-identity-high (both deprecated)POST /digital-identity-medium-m1a
Candidate journeyOnfido SDK tokenHosted data.url; no SDK token
ResultsGET /digital-identity-check-results?uuid=...GET /digital-identity-results?uuid=...
SDK tokenPOST /digital-identity-generate-sdk-tokenNot applicable

Routes above are relative to your API base URL, which includes /api. Onfido Medium creation, High creation, results and SDK-token generation all set the operation-wide OpenAPI deprecated flag. Both Swagger UIs display deprecation under Medium and High. The supplier callback (POST /digital-identity-webhook) remains unchanged for in-flight Onfido checks and is deliberately excluded from public Swagger.

Deprecation does not disable any route. Existing Onfido checks must continue using the Onfido results, SDK-token and callback routes. Do not send an existing Onfido UUID to the Trust ID results route or reinterpret Onfido results as Trust ID containers. The separate Trust ID create/results operations are not deprecated, even though they share the Medium Swagger tag.

Create a check​

The M1A candidate payload requires only first name, last name and email. Do not send X-Check-Version: next for M1A: this route is not version-switched. Do not copy the additional Onfido candidate fields or address payload into the M1A integration.

{
"candidate": {
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com"
},
"metaData": {
"yourReference": "your-unique-reference",
"demoMode": true,
"sandboxMode": false,
"customerName": "Example Customer"
}
}

Read the check identifier from uuid and open data.url, not data.linkUrl. The early M1A preview field linkUrl has been renamed to url; clients using the preview contract must update their deserialization. The redundant data.backgroundCheckUuid duplicate of uuid has been removed; uuid is the only check reference.

{
"uuid": "12345678-1234-1234-1234-123456789012",
"data": {
"url": "https://YOUR_API_HOST/api/trust-id-demo",
"detail": "Digital Identity Check (medium) created successfully."
}
}

The example URL is for demo information only. Live and supplier-sandbox checks return Trust ID's hosted guest link unchanged. Share that supplier URL with the candidate; no Onfido SDK initialization or SDK-token refresh is involved.

Completion and results​

Creation is asynchronous. Poll GET /digital-identity-results?uuid=... or use the existing completion notification integration. Successful creation does not mean identity verification succeeded.

The results data object follows the standard Access Checks layout: data.container carries the native Trust ID document container unchanged — including OverallStatus, Documents, DocumentContainerFieldList and DocumentContainerValidationList — with supplier field casing, values and collections retained and only internal __SYSTEM_ fields removed. data.reportUrl, data.documentImages and data.expired sit alongside it inside data. The Onfido checks/reports model does not apply. See Swagger for the generated schema.

Incomplete live/sandbox checks expire after the 14-day guest-link window and are not billed. Once a native terminal result is saved, pending evidence is resolved by the evidence retry policy rather than guest-link expiry.

Evidence is resolved before Completed​

The platform automatically retrieves the supplier PDF, uploaded selfie and eligible document images. The check remains Processing until every item is either validated and stored with readable blob bytes and eligible attachment metadata, or terminally unavailable. The first Completed response contains the final evidence URLs or explicit nulls. Later polling does not add evidence to that completed result.

Every results entry includes reportUrl and documentImages inside data, beside container and expired. This abbreviated response illustrates multiple images and partial availability:

[
{
"status": "Completed",
"data": {
"container": { "Id": "11111111-2222-3333-4444-555555555555" },
"reportUrl": "api/check-attachment?uuid=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee&id=456",
"documentImages": [
{
"documentType": "selfie",
"createdAt": "2026-04-09T06:30:42.6408887Z",
"fileName": "stored-selfie-filename",
"fileType": "image/jpeg",
"url": "api/check-attachment?uuid=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee&id=457"
},
{
"documentType": "passport",
"createdAt": "2026-04-09T06:30:43.1234567Z",
"fileName": "stored-document-filename",
"fileType": "image/png",
"url": "api/check-attachment?uuid=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee&id=458"
},
{
"documentType": "passport",
"createdAt": null,
"fileName": null,
"fileType": null,
"url": null
}
],
"expired": false
}
}
]

data.container is the Trust ID document container as Trust ID produced it and is absent until a native result exists. data.expired replaces the former top-level outcome: it is true when the platform completed the check because the 14-day guest-link window passed without the candidate completing — such results carry status: "Completed", no container and no evidence — and false otherwise.

Resolve each URL against the API origin and use the normal bearer token. These are authenticated api/check-attachment?uuid=...&id=... paths restricted to the check's customer. No public blob or supplier URL is returned. Downloading never calls Trust ID or changes completion/billing. Stored evidence remains available after the guest-link window expires. data.url in the creation response is still the candidate's guest link.

Before evidence metadata is available, and for expiry/error results without native data, the properties remain present inside data:

{
"data": {
"reportUrl": null,
"documentImages": [],
"expired": false
}
}

Each documentImages object has exactly documentType, createdAt, fileName, fileType and url. Filenames, UTC creation times and MIME types describe the actual persisted attachment. The sample values above are illustrative.

The available applicant photo appears once with documentType: "selfie". Native data.container.ApplicantPhotoImage is preserved. Document images use their parent document's canonical type:

Trust ID document metadataPublic documentType
DocumentType: 0 (Passport)passport
DocumentType: 3 (DrivingLicence)driving_licence
DocumentType: 2, DocumentName: "Passport Card" (for example an Irish passport card)passport
DocumentType: 2, DocumentName: "ID Card"national_identity_card
DocumentType: 2, DocumentName: "Biometric Residence Permit"residence_permit
Other identity-card subtypes, missing/unknown types, Visa, SupportingDocument, Unrecognised, OnlineCheck and OnlineRTRChecknull

Subtype names are matched case-insensitively, ignoring surrounding whitespace. Trust ID reports a two-image passport card (face and back uploads) as DocumentType: 2 (IdentityCard) with a PASSPORT CARD/Passport Card name; the platform reports it as passport because the document is a passport. Work permits and voter IDs have no verified Trust ID subtype mapping and remain null. Internal image/document IDs and image types are not exposed in this projection; native data.container is unchanged. See Trust ID's document types and document name guidance.

Repeated references to the same supplier image produce one entry and one evidence acquisition per attempt. Distinct front/back images and distinct documents remain separate even when their filenames or MIME types match. The PDF remains outside the array, in reportUrl.

documentImages is always an array: [] when there is no evidence, no eligible images, no available persisted image attachments, or in demo mode where image fixtures do not exist. This also applies to Pending, Processing, expired and error results. With partial availability, eligible unavailable images retain their known documentType, with explicit null createdAt, fileName, fileType and url; a set with no available images returns []. An available URL during Processing already identifies persisted, validated bytes. A null during Processing may change; a null on Completed is final.

Availability, retries and validation​

Supplier absence or nonretryable content-validation failure resolves an item to null immediately. Transient supplier, blob or metadata failures receive five delayed retries at 1, 10, 30, 60 and 480 minutes. After the sixth attempt, unresolved items become terminal null; successfully stored evidence keeps its URLs. Native terminal data and progress are persisted before completion, so retries and restarts do not refetch native results. Queue-send failure fails the delivery for Azure Storage Queue redelivery.

Evidence uses existing attachment storage and metadata, without a migration. Renewable per-check leases coordinate callbacks, workers and guest-link expiry. Completion stages customer notifications transactionally with the completed result. Billing keeps its check-based idempotency key. Historical completed checks are not backfilled; old queued report-download messages cannot mutate them.

The PDF comes from Trust ID's documented exportPDF, with a fresh login/session, configured device ID and saved container ID. PDFs must declare application/pdf or application/octet-stream, have %PDF- and %%EOF markers, and fit within 20 MiB. Valid octet-stream bodies are stored as application/pdf.

Images use a fresh login → retrieveImage with the selected image ID → logout:

EvidenceNative metadata
Selfiedata.ApplicantPhotoImage.Id, only when ImageType is 1 (Face).
Front/full documentType 60 (OriginalDocument), or type 2 (Document) when no original for that capture is present in the container.
Document backType 62 (OriginalDocumentBack), or type 52 (DocumentBack) when no original back for that capture is present.
Additional sidesTypes 72 (DocumentSide3) and 82 (DocumentSide4).

ImageSourceId links derived representations to their source capture. The projection selects one representation per linked capture within the same document and side, preferring the original. Repeated IDs are deduplicated. Unlinked captures, separate documents, backs and additional sides remain distinct even when filenames or MIME types match. A stored representation from an interrupted older attempt is reused rather than downloading its original again; cached older state is also projected only once per capture. Native supplier data and existing attachment records are not rewritten. Original preference is based on metadata presence; a selected image that cannot be acquired follows the null-evidence rules above.

Trust ID's documented image types define no separate original-image type for side 3 or side 4. Types 73/74 and 83/84 are infrared/ultraviolet images, not original/derived alternatives. Linked captures sharing type 72 or 82 are still grouped through ImageSourceId; unlinked captures remain distinct.

Evidence retries reuse the persisted terminal container rather than refreshing the supplier's representation set. If legacy evidence already contains multiple stored representations of one capture, selection narrows the processing/projection state only. Unselected attachment rows and blobs remain owned by the same check and customer; normalization does not delete stored evidence or acquire replacement images.

Explicit container/document ownership must match. Document-associated Face (1) and DetectedFace (9) crops, infrared/ultraviolet variants, RFID face, barcode, MRZ, fingerprint, OCR and unknown image types are excluded. Only the application-level ApplicantPhotoImage is the selfie. Container, check, document and detected-face IDs are not substitutes for uploaded image IDs. Availability is independent of pass/fail verdict.

Images must be structurally valid JPEG or PNG within 20 MiB, including any trailing bytes. Valid trailing bytes after EOI/IEND are preserved. Valid octet-stream images are normalized to their detected MIME type. Empty, malformed, truncated, oversized, mismatched, SVG, GIF and HTML content is rejected. Supplier logging contains metadata only.

The preview GET /api/digital-identity/{checkUuid}/images/{imageId} endpoint is removed. Consumers use the automatically populated result URLs and common authenticated attachment route.

Demo versus supplier sandbox​

Use demoMode: true and sandboxMode: false for platform simulation. The terminal result is queued automatically without candidate action. data.url opens a public, read-only information page; opening it does not complete a check. Demo requires no Trust ID configuration and makes no supplier calls.

sandboxMode: true uses the real supplier sandbox even when demoMode is also true. It requires sandbox configuration and the normal supplier journey. Effective stored customer/request modes govern processing and billing; surnames do not select scenarios in live/sandbox.

candidate.lastNameDemo result
Expired Passport or ExpiredPassportFailed expired-passport specimen and sanitized expired-passport PDF.
HappyPath or any other surnamePassed specimen and sanitized passed PDF.

Matching ignores case and surrounding spaces. Old SoftFail, FakePassport, FaceNotMatched and ExpiredGuestLink names use the default passed specimen. Genuine live/sandbox adverse outcomes and actual guest-link expiry remain supported.

Both demo PDFs are static sanitized supplier samples, not evidence about the submitted candidate. They are validated and stored before Completed, with a ready data.reportUrl. No image byte fixtures exist: data.documentImages is []. No images are extracted from the PDFs or invented.

Demo preserves the native specimens' field casing, numeric verdicts, nulls and collections inside data.container. A failed verification is still a successfully retrieved Completed check; inspect the native validation details rather than treating platform status as a verdict.

API verification checklist​

  1. Create demo checks with Expired Passport, ExpiredPassport, HappyPath and an ordinary surname. Poll results with the returned UUID. The first Completed response must have a usable report URL and explicit null image URLs. The expired-passport cases must retain failed native validations; the others must pass.
  2. Download each report URL with the same customer token and confirm a sanitized PDF. Repeat results/download requests; URLs and completion timestamp must remain stable.
  3. In a controlled supplier mock environment, provide a PDF, selfie and multiple document images. Poll during storage, then on completion. Available URLs must download the expected bytes and MIME types through the common attachment route.
  4. In the mock environment, exercise missing, invalid and temporarily unavailable evidence. Missing/invalid items become null; transient failures remain Processing during bounded retries. Successful items retain their URLs when other items exhaust retries.
  5. Try an attachment with another customer's token and with a different check UUID. It must not return the file. Verify existing Onfido create/results/download flows remain operational.

Billing during coexistence​

Non-demo, non-sandbox Trust ID M1A checks use the existing Onfido Medium billing configuration temporarily: catalogue rates, customer-specific PAYG rates and existing Medium credits. Billing is dispatched once evidence is resolved, before completion is published. Existing Onfido creation-time billing is unchanged. Demo, sandbox and guest-link-expired checks are not billed.

The adapter preserves check identity and check-level idempotency. It does not create a second balance, redesign billing, replay historical charges or repair old data. Portal price previews use the same configuration.

Removal condition (AB#2607813): remove the Supplier billing-dispatch and Portal pricing-preview adapters together only after Onfido Medium retirement and the explicit migration of its billing configuration and remaining balances.