Authentication
Send your company's developer key as a bearer token on every request:Authorization: Bearer ms_live_.... Keys are created, rotated and given an expiry in MIRA Business under Settings, API Keys, by the company owner. Rotating a key stops the old one immediately.
A key belongs to one company. A dealer's key can start every journey type; a broker's key can start every finance sale. Everything a key can see is limited to journeys its company started.
Sandbox
Test keys (ms_test_) run the same API against simulated journeys. They never create a real customer or handover, never charge your wallet, and never email a customer: journey emails go to your company admin instead, marked TEST. Photos you send are still checked, then thrown away. Responses and webhooks say"livemode": false.
A test journey moves on by itself every few seconds. To force an outcome, callPOST /{journeyId}/simulate with an event from the catalogue marked simulatable. Live and test data never mix: a live key cannot see test journeys, and the other way round.
Idempotency
Starting a journey needs an Idempotency-Key header (8 to 255 letters, digits, or . _ : -), unique per journey. Use something from your own system, such as your deal number. Sending the same key again with the same body returns the original journey with status 200 and an Idempotent-Replayed: trueheader instead of starting a second one, so it is always safe to retry after a timeout or a 503. The same key with a different body is refused withIDEMPOTENCY_KEY_REUSED. If a request fails, nothing is kept and you can retry with the same key.
Responses
Every response uses the same envelope. On failure, errors[0].code is the stable code to act on.
{
"success": true,
"data": {
"id": "0192f1c2-6f3b-7d2a-9d6e-1a2b3c4d5e6f",
"type": "IDENTITY_DELIVERY",
"status": "ACTIVE",
"livemode": false,
"externalReference": "DMS-88213",
"customerReference": "5f1c7a9e-6f3b-4d2a-9d6e-1a2b3c4d5e6f",
"delivery": null,
"finance": null,
"identity": { "status": null },
"nextAction": "CUSTOMER_TO_VERIFY_IDENTITY",
"createdAt": "2026-09-25T10:15:02Z"
},
"message": "Journey started",
"errors": null
}{
"success": false,
"data": null,
"message": "Identity verification is not set up for this company. Configure it in MIRA Business first.",
"errors": [{ "field": "journey", "code": "EKYC_NOT_CONFIGURED", "message": "..." }]
}Starting a journey
POST https://api.motorsync.co.uk/api/v1/journeys. Use the customer's own email address: it is where MIRA sends their sign-in links. The journey identifies the customer with its own customerReference. Pick the journey that matches what has already happened outside MIRA:
| type | Use it when | What MIRA does |
|---|---|---|
FINANCE_IDENTITY_DELIVERY | The full flow for a financed sale: the finance application, then the customer's identity check, then the verified handover. | You send the deal. Either it is already on your own finance panel (ALREADY_SUBMITTED, with your panel reference), or you send the full application and MIRA submits it to your configured panel (SUBMIT_VIA_MIRA). The customer gets a sign-in link and verifies their identity in the app. The lender decision comes from you (ALREADY_SUBMITTED) or from the panel (SUBMIT_VIA_MIRA). Once finance is approved and the customer is verified, the handover is created and the customer completes it in the app. |
IDENTITY_DELIVERY | For a financed sale already approved on your own panel. You send who to verify; MIRA runs the identity check, tells you the result, then runs the handover. | You send the customer, vehicle and handover details, and optionally your panel name, reference and lender. No finance application is needed: it is recorded as approved. The customer gets a sign-in link and verifies their identity in the app. As soon as they are verified, the handover is created and the customer completes it in the app. |
DELIVERY | A verified handover with no finance application in MIRA. Say whether it is a cash sale or a finance sale. | CASH_SALE: the customer verifies their identity and, for a home delivery, confirms their address in the app, then completes the handover. FINANCE_SALE: the finance and identity checks happened outside MIRA, so you send a photo of the customer with their consent, used to verify the handover. A match completes the handover; anything unclear goes to your team to review. |
curl -X POST https://api.motorsync.co.uk/api/v1/journeys \
-H "Authorization: Bearer ms_test_..." \
-H "Idempotency-Key: deal-88213" \
-H "Content-Type: application/json" \
-d '{
"type": "IDENTITY_DELIVERY",
"externalReference": "DMS-88213",
"customer": {
"firstName": "Jane", "lastName": "Doe",
"email": "jane@example.com", "mobile": "07700900000"
},
"vehicle": { "registration": "AB21XYZ", "make": "BMW", "model": "3 Series", "year": 2021 },
"delivery": { "type": "HOME_DELIVERY" },
"finance": { "panelName": "iVendi", "panelReference": "IV-123456", "lender": "Close Brothers" }
}'Request fields
Required means the request is refused without it. Codes must be sent exactly as listed. Anything not listed for a journey type is refused rather than ignored, so you never believe a field is being used when it is not.
Top level
| Field | Required | Rules |
|---|---|---|
type | Always | FINANCE_IDENTITY_DELIVERY, IDENTITY_DELIVERY or DELIVERY |
externalReference | No | Your own id for the deal, up to 100 characters. You can list journeys by it. |
externalCompanyName | No | The selling company's name, for example the dealer a broker is working with, up to 255 characters |
customer | Always | See below |
vehicle | Always | See below |
delivery | Always | See below |
customerFace | DELIVERY with FINANCE_SALE only | See below. Refused for every other journey. |
finance | FINANCE_IDENTITY_DELIVERY; optional for IDENTITY_DELIVERY | See below. Refused for DELIVERY. |
customer
Use the customer's own email address: it is where MIRA sends their sign-in links.
| Field | Required | Rules |
|---|---|---|
firstName, lastName | Always | Up to 100 characters each |
email | Always | A valid email, up to 255 characters |
mobile | SUBMIT_VIA_MIRA | 10 to 20 characters: digits, spaces, + - ( ) |
title | SUBMIT_VIA_MIRA | MR, MRS, MISS, MS or DR |
dateOfBirth | SUBMIT_VIA_MIRA | YYYY-MM-DD |
vehicle
| Field | Required | Rules |
|---|---|---|
registration | Always | Up to 20 characters |
make | No | Up to 50 characters |
model | No | Up to 100 characters |
year | No | 1900 to 2100 |
colour | No | Up to 50 characters |
inventoryVehicleId | No | Your MIRA stock vehicle id; it is marked sold when the handover completes |
delivery
| Field | Required | Rules |
|---|---|---|
type | Always | IN_STORE or HOME_DELIVERY. A home delivery asks the customer to confirm the address in the app. |
saleType | DELIVERY only | CASH_SALE (identity check in the app) or FINANCE_SALE (you send customerFace). Refused for the other journeys, which are always finance sales. |
notes | No | Up to 1000 characters, for your team. Never shown to the customer. |
customerFace (DELIVERY, FINANCE_SALE)
Sent as a "journey" JSON part plus a "customerFace" file part (JPEG or PNG, one clear face, up to 5 MB) in a multipart request.
| Field | Required | Rules |
|---|---|---|
source | Yes | IN_PERSON_PHOTO or ID_DOCUMENT_PHOTO |
capturedAt | No | When the photo was taken (ISO 8601) |
biometricConsent.given | Yes | Must be true |
biometricConsent.capturedAt | Yes | When the customer consented (ISO 8601) |
biometricConsent.method | Yes | SIGNED_IN_PERSON or ONLINE_FORM |
biometricConsent.noticeVersion | Yes | The privacy notice the customer saw, up to 100 characters |
biometricConsent.capturedBy | No | Who took the consent, up to 255 characters |
finance
IDENTITY_DELIVERY only takes panelName, panelReference and lender; anything else is refused.
| Field | Required | Rules |
|---|---|---|
panelSubmission | FINANCE_IDENTITY_DELIVERY | ALREADY_SUBMITTED or SUBMIT_VIA_MIRA |
panelName | ALREADY_SUBMITTED | Your panel, up to 20 characters |
panelReference | ALREADY_SUBMITTED | The application on your panel, up to 100 characters |
decision | No (ALREADY_SUBMITTED only) | APPROVED, DECLINED or REFERRED, if already known |
lender | No | Up to 50 characters |
vehiclePrice | SUBMIT_VIA_MIRA | Cash price, above 0 |
loanTerm | SUBMIT_VIA_MIRA | Months, 12 to 120 |
depositAmount | No | 0 or more (default 0) |
monthlyBudget | No | 0 or more |
maritalStatus | No | SINGLE, COHABITING, MARRIED, SEPARATED, DIVORCED, WIDOWED, CIVIL_PARTNERSHIP, DISSOLVED_CIVIL_PARTNERSHIP, ENGAGED |
drivingLicenceType | SUBMIT_VIA_MIRA | FULL_UK, PROVISIONAL_UK, CBT, A2, FULL_A_CLASS, EUROPEAN, INTERNATIONAL, NONE |
validUkPassport | No | true or false |
employmentHistory[] | SUBMIT_VIA_MIRA | Up to 10 entries, at least one CURRENT. See below. |
addressHistory[] | SUBMIT_VIA_MIRA | Up to 10 entries, exactly one CURRENT, covering at least 3 years in total. See below. |
consents | SUBMIT_VIA_MIRA | See below |
finance.employmentHistory[] (SUBMIT_VIA_MIRA)
| Field | Required | Rules |
|---|---|---|
employmentType | Yes | CURRENT or PREVIOUS |
employmentStatus | Yes | FULL_TIME_EMPLOYMENT, PART_TIME_EMPLOYMENT, SELF_EMPLOYED, RETIRED, HOMEMAKER, CARER, BENEFITS |
employer | Yes | Up to 255 characters. For RETIRED, HOMEMAKER, CARER or BENEFITS, send the status in words (for example "Retired"). |
jobTitle | Yes | Up to 255 characters (as for employer when not employed) |
monthlyIncome | Yes | Above 0 |
timeAtEmployerYears | No | 0 to 50 (default 0) |
timeAtEmployerMonths | No | 0 to 11 (default 0) |
finance.addressHistory[] (SUBMIT_VIA_MIRA)
| Field | Required | Rules |
|---|---|---|
addressType | Yes | CURRENT or PREVIOUS |
street | Yes | Up to 255 characters |
city | Yes | Up to 100 characters |
postcode | Yes | Up to 20 characters |
buildingNumber, buildingName | No | Up to 20 and 100 characters |
subBuildingName, organisationName, county | No | Up to 100 characters |
timeAtAddressYears | No | 0 to 100 (default 0) |
timeAtAddressMonths | No | 0 to 11 (default 0) |
residentialStatus | No | HOMEOWNER, JOINT_OWNER, TENANT_PRIVATE, TENANT_PRIVATE_UNFURNISHED, TENANT_HOUSING_ASSOCIATION, TENANT_COUNCIL, LIVING_WITH_FAMILY, MILITARY_ACCOMMODATION, WORK_ACCOMMODATION, STUDENT_ACCOMMODATION, OTHER |
finance.consents (SUBMIT_VIA_MIRA)
The consents the customer gave you for this application. The application goes to the lender panel as soon as it is accepted, so all of them must be true.
| Field | Required | Rules |
|---|---|---|
infoAccuracy | Yes | true: the customer confirmed their details are accurate |
motorsyncTerms | Yes | true: accepted the MIRA terms |
providerTerms | Yes | true: accepted the finance provider's terms and privacy policy |
dataSharing | Yes | true: agreed to share their details with the provider and its lenders |
creditCheck | Yes | true: agreed to a soft credit search |
identityVerification | Yes | true: agreed to identity verification, including biometric checks |
providerName | Yes | The finance provider the customer agreed to, up to 255 characters |
Identity check and handover (IDENTITY_DELIVERY)
For a financed sale already approved on your own panel. No finance application is needed: MIRA records it as approved, with your panelName, panelReference and lender if you send them. The customer is asked to verify their identity straight away. You are told the result through identity.* events, and as soon as they are verified the handover is created. No photo is needed.
Handover only (DELIVERY)
For a handover with no finance application in MIRA. delivery.saleType says which kind of sale it is:
| saleType | Identity | Who can send it |
|---|---|---|
CASH_SALE | The customer verifies their identity in the MIRA app, and confirms the address for a home delivery. | Dealer keys |
FINANCE_SALE | Checked with the finance, outside MIRA. You send customerFace, used to verify the handover. | Dealer or broker keys |
curl -X POST https://api.motorsync.co.uk/api/v1/journeys \
-H "Authorization: Bearer ms_test_..." \
-H "Idempotency-Key: deal-88215" \
-H "Content-Type: application/json" \
-d '{
"type": "DELIVERY",
"customer": { "firstName": "Alex", "lastName": "Khan", "email": "alex@example.com" },
"vehicle": { "registration": "EF23GHI" },
"delivery": { "type": "HOME_DELIVERY", "saleType": "CASH_SALE" }
}'For a FINANCE_SALE, send the request as multipart/form-data with a journey JSON part and a customerFace part: a JPEG or PNG up to 5 MB showing exactly one clear face. It is stored without its metadata and checked before anything is created. Using someone's face this way needs their explicit consent, which you confirm in customerFace.biometricConsent. It is recorded with the handover.
curl -X POST https://api.motorsync.co.uk/api/v1/journeys \
-H "Authorization: Bearer ms_test_..." \
-H "Idempotency-Key: deal-88214" \
-F 'journey={
"type": "DELIVERY",
"customer": { "firstName": "Sam", "lastName": "Lee", "email": "sam@example.com" },
"vehicle": { "registration": "CD22ABC" },
"delivery": { "type": "IN_STORE", "saleType": "FINANCE_SALE" },
"customerFace": {
"source": "IN_PERSON_PHOTO",
"biometricConsent": {
"given": true, "capturedAt": "2026-09-25T10:15:00Z",
"method": "SIGNED_IN_PERSON", "noticeVersion": "privacy-v3", "capturedBy": "Front desk"
}
}
};type=application/json' \
-F 'customerFace=@sam.jpg;type=image/jpeg'If the video keeps failing to match, replace the photo with PUT /{journeyId}/customer-face while no video is being checked.
Full flow with finance (FINANCE_IDENTITY_DELIVERY)
Choose how the application reaches a lender with finance.panelSubmission:
| panelSubmission | Use it when | The decision comes from |
|---|---|---|
ALREADY_SUBMITTED | The deal is already on your own finance panel. Send panelName and panelReference; MIRA never submits it anywhere. | You, with POST /{journeyId}/finance-decision, or finance.decision at creation if you already know it |
SUBMIT_VIA_MIRA | You want MIRA to submit the application to the finance panel set up in MIRA Business. Send the full application. | The panel, automatically |
"type": "FINANCE_IDENTITY_DELIVERY",
"finance": {
"panelSubmission": "ALREADY_SUBMITTED",
"panelName": "iVendi",
"panelReference": "IV-123456",
"lender": "Close Brothers",
"vehiclePrice": 15000, "loanTerm": 48, "depositAmount": 1000
}For SUBMIT_VIA_MIRA the application goes to the panel as soon as it is accepted, so it must be complete and use the codes listed in Request fields, with at least 3 years of address history and the consents the customer gave you. It is sent with the current job and address first.
"type": "FINANCE_IDENTITY_DELIVERY",
"customer": { ..., "title": "MRS", "mobile": "07700900000", "dateOfBirth": "1990-04-12" },
"finance": {
"panelSubmission": "SUBMIT_VIA_MIRA",
"vehiclePrice": 15000, "loanTerm": 48, "depositAmount": 1000, "monthlyBudget": 350,
"maritalStatus": "MARRIED", "drivingLicenceType": "FULL_UK", "validUkPassport": true,
"employmentHistory": [{
"employmentType": "CURRENT", "employmentStatus": "FULL_TIME_EMPLOYMENT", "employer": "Acme Ltd",
"jobTitle": "Engineer", "monthlyIncome": 3200, "timeAtEmployerYears": 4, "timeAtEmployerMonths": 2
}],
"addressHistory": [{
"addressType": "CURRENT", "buildingNumber": "12", "street": "High Street", "city": "Leeds",
"postcode": "LS1 4AB", "timeAtAddressYears": 5, "timeAtAddressMonths": 0, "residentialStatus": "TENANT_PRIVATE"
}],
"consents": {
"infoAccuracy": true, "motorsyncTerms": true, "providerTerms": true, "dataSharing": true,
"creditCheck": true, "identityVerification": true, "providerName": "CarMoney"
}
}The customer is asked to verify their identity once the application is recorded (for SUBMIT_VIA_MIRA, once the panel has accepted it), while the decision is pending. The handover is created only when finance is approved and identity is verified, in either order. A declined application, or one that could not be submitted to the panel (finance_enquiry.submission_failed), ends the journey.
Before accepting a journey that includes an identity check, MIRA checks that identity verification is set up for your company, that a finance panel is set up for SUBMIT_VIA_MIRA, and that the wallets that pay for the checks have enough credit. Each check is billed exactly as when your team starts it in MIRA.
The journey object
status is ACTIVE, COMPLETED, CANCELLED or EXPIRED. delivery has the handoverdelivery.status follows the handover,apos;s statusand, for DELIVERY journeys, its saleType. identity appears on FINANCE_IDENTITY_DELIVERY and IDENTITY_DELIVERY, finance on FINANCE_IDENTITY_DELIVERY only (a cash-sale DELIVERY's identity step shows in delivery.status), and nextAction says what the journey is waiting for:
| nextAction | Meaning |
|---|---|
CUSTOMER_TO_VERIFY_IDENTITY | The customer needs to complete the identity check. |
CUSTOMER_TO_CONFIRM_ADDRESS | The customer needs to confirm the delivery address. |
CUSTOMER_TO_RECORD_VIDEO | The customer needs to record the handover video. |
DEALER_TO_REVIEW | Your team needs to review the identity check or video. |
IDENTITY_UNDER_REVIEW | The identity check is with a reviewer. |
SEND_FINANCE_DECISION | Send the lender decision (ALREADY_SUBMITTED). |
AWAITING_LENDER_DECISION | Waiting for the panel decision (SUBMIT_VIA_MIRA). |
HANDOVER_BEING_CREATED | Finance is approved and identity verified; the handover is being set up. |
Endpoints
| Method | Path | What it does |
|---|---|---|
| POST | /api/v1/journeys | Start a journey. JSON body, or multipart with a "journey" part and a "customerFace" photo for DELIVERY journeys. Needs an Idempotency-Key header. Returns 202, or 200 with an Idempotent-Replayed: true header and the original journey when the same key is replayed. |
| GET | /api/v1/journeys/{journeyId} | Get a journey. |
| GET | /api/v1/journeys | List journeys. Newest first. Filters: status, externalReference. Paging: page (from 0), size (up to 100). |
| POST | /api/v1/journeys/{journeyId}/cancel | Cancel a journey. Body: { "reason": "..." } (10 to 500 characters). Refused once the journey has finished. |
| PUT | /api/v1/journeys/{journeyId}/customer-face | Replace the customer photo. DELIVERY journeys only, while no video is being checked. Multipart: "details" (source and consent) and "customerFace". |
| POST | /api/v1/journeys/{journeyId}/finance-decision | Report the lender decision. ALREADY_SUBMITTED finance journeys only. Body: { "decision": "APPROVED" | "DECLINED" | "REFERRED" }. |
| POST | /api/v1/journeys/{journeyId}/simulate | Force the next outcome (sandbox). Test keys only. Body: { "event": "delivery.completed" } or any event marked "simulatable" below. |
What customers receive
A new customer gets a welcome email first. Then, at each step that needs them (verify identity, confirm the delivery address, record the handover video) they get an email with a one-time sign-in link that opens the MIRA app on that step. They also hear when finance is approved or updated and when the handover is complete. Emails are sent in your company's name.
Webhooks
Add an endpoint in MIRA Business under Settings, Webhooks: one for live events and, separately, one for test events. It must be HTTPS on port 443 or 8443 and reachable from the public internet. You see its signing secret once, when you add it or replace it.
MIRA sends a POST for each event on journeys you started through the API. By default that is every event; in settings you can choose only some, by name or by whole group (a group also covers events added to it later). The test event is always sent. Events carry ids and statuses only, never personal details: callGET /api/v1/journeys/{journeyId} for more.
POST /your/webhook/path
Mira-Event-Id: 0192f1d0-2a4b-7c3d-8e9f-0a1b2c3d4e5f
Mira-Event-Type: delivery.completed
Mira-Timestamp: 1759140000
Mira-Signature: t=1759140000,v1=<64 hex characters>
{
"id": "0192f1d0-2a4b-7c3d-8e9f-0a1b2c3d4e5f",
"type": "delivery.completed",
"apiVersion": "1.0.0",
"livemode": true,
"createdAt": "2026-10-02T14:03:11Z",
"data": {
"journeyId": "0192f1c2-6f3b-7d2a-9d6e-1a2b3c4d5e6f",
"journeyType": "IDENTITY_DELIVERY",
"journeyStatus": "COMPLETED",
"externalReference": "DMS-88213",
"customerReference": "5f1c7a9e-6f3b-4d2a-9d6e-1a2b3c4d5e6f",
"deliveryStatus": "COMPLETED"
}
}Check every request. Mira-Signature ist=<unix seconds>,v1=<hex>, where v1 is HMAC-SHA256 of t + "." + raw bodykeyed with your secret. Compute it over the exact bytes you received, compare in constant time, and reject at more than 5 minutes old so an old request cannot be replayed.
const crypto = require('crypto')
// rawBody must be the exact bytes received, before any JSON parsing.
function verifyMiraSignature(rawBody, header, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
const t = Number(parts.t)
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false
const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex')
const given = Buffer.from(parts.v1 || '', 'hex')
return given.length === 32 && crypto.timingSafeEqual(given, Buffer.from(expected, 'hex'))
}Answer quickly. Any 2xx within 10 seconds counts as delivered. Redirects are not followed. Anything else is retried after 1 minute, 5 minutes, 30 minutes, 2, 6, 12 and 24 hours, then given up on. The same event can arrive more than once and out of order, so useMira-Event-Id to ignore repeats and createdAt or a fresh GET for the latest state.
If nothing reaches an endpoint for three days, MIRA turns it off and emails your company admin. Fix it, save the URL again to turn it back on, and resend what you missed from the delivery log.
Event catalogue
Every event has id, type, apiVersion, livemode,createdAt and data (journeyId, journeyType, journeyStatus, externalReference, customerReference, deliveryStatus, and financeStatus and identityStatus on finance journeys).
Journey
| Event | When | Sandbox |
|---|---|---|
journey.created | The journey was accepted. | |
journey.customer_face_replaced | You replaced the customer photo. | |
journey.completed | The handover is complete. Nothing more will happen. | |
journey.cancelled | The journey ended without a handover (cancelled, declined, or the application could not be submitted). | |
journey.expired | The customer did not finish in time. |
Finance
| Event | When | Sandbox |
|---|---|---|
finance_enquiry.submitted | FINANCE_IDENTITY_DELIVERY only: the application is recorded (and, for SUBMIT_VIA_MIRA, being sent to your panel). Finance events are not sent for IDENTITY_DELIVERY, which is approved from the start. | |
finance_enquiry.approved | Finance is approved. | simulatable |
finance_enquiry.declined | Finance is declined. The journey is cancelled. | simulatable |
finance_enquiry.referred | The lender referred the application. It stays pending. | simulatable |
finance_enquiry.submission_failed | SUBMIT_VIA_MIRA only: the application could not be sent to your panel. data.reason is PANEL_NOT_CONFIGURED, PANEL_ERROR or SUBMISSION_ERROR. The journey is cancelled; start a new one to try again. | simulatable |
Identity
| Event | When | Sandbox |
|---|---|---|
identity.requested | The customer has been asked to verify their identity (finance journeys, IDENTITY_DELIVERY and cash-sale DELIVERY). | |
identity.verified | The customer is verified. | simulatable |
identity.under_review | The check needs a person to look at it. | simulatable |
identity.failed | The check failed. The customer can try again. | simulatable |
identity.unavailable | The check could not be started. data.reason is EKYC_NOT_CONFIGURED or PROVIDER_ERROR. The journey stays open and continues once your team resends the check. |
Handover
| Event | When | Sandbox |
|---|---|---|
delivery.created | The handover exists. data.deliveryStatus says what the customer does first. | |
delivery.location_confirmed | The customer confirmed the delivery address (home delivery). | simulatable |
delivery.awaiting_video | The customer can record their handover video. | simulatable |
delivery.video_uploaded | The video arrived and is being checked. | simulatable |
delivery.under_review | The video needs your team to review it. | simulatable |
delivery.completed | The handover was verified. | simulatable |
delivery.cancelled | The handover was cancelled. | simulatable |
delivery.expired | The handover window passed. | simulatable |
Other
| Event | When | Sandbox |
|---|---|---|
ping | Sent when you press "Send test event" in settings. |
Errors
| Status | Code | What to do |
|---|---|---|
| 400 | IDEMPOTENCY_KEY_REQUIRED | Send an Idempotency-Key header: 8 to 255 letters, digits, or . _ : - |
| 400 | APPLICATION_INCOMPLETE | SUBMIT_VIA_MIRA is missing fields, has no single CURRENT address, or less than 3 years of address history. The message says which. |
| 400 | PANEL_REFERENCE_REQUIRED | ALREADY_SUBMITTED needs finance.panelName and finance.panelReference. |
| 400 | PANEL_FIELDS_NOT_USED | SUBMIT_VIA_MIRA does not take panelName, panelReference or decision. |
| 400 | SALE_TYPE_REQUIRED / SALE_TYPE_NOT_USED | DELIVERY needs delivery.saleType; the other journeys must not send it. |
| 400 | CUSTOMER_FACE_REQUIRED / CUSTOMER_FACE_NOT_USED | A FINANCE_SALE DELIVERY needs a customerFace photo; every other journey must not send one. |
| 400 | FINANCE_FIELDS_NOT_USED | IDENTITY_DELIVERY only takes panelName, panelReference and lender. |
| 400 | INVALID_APPLICATION_VALUE | A SUBMIT_VIA_MIRA code (marital status, licence, employment or residential status) is not one the panels accept. The message lists the allowed values. |
| 400 | UNSUPPORTED_IMAGE_TYPE | customerFace must be a JPEG or PNG. |
| 401 | INVALID_API_KEY | The key is wrong, revoked, or not a developer key. |
| 401 | API_KEY_EXPIRED | The key has passed its expiry date. |
| 403 | API_KEY_NOT_PERMITTED | The key may not call this endpoint. |
| 404 | JOURNEY_NOT_FOUND | No such journey for this key. Live keys never see test journeys, and the other way round. |
| 409 | IDEMPOTENCY_KEY_REUSED | The Idempotency-Key was used before with a different request. |
| 409 | FINANCE_DECISION_FROM_PANEL | SUBMIT_VIA_MIRA decisions come from the lender panel. |
| 409 | FINANCE_ALREADY_DECIDED | A decision is already recorded. |
| 409 | CUSTOMER_FACE_LOCKED | The photo cannot change while a video is being checked or after the handover. |
| 409 | JOURNEY_FINISHED | The journey has already ended. |
| 422 | BIOMETRIC_CONSENT_REQUIRED | customerFace.biometricConsent.given must be true. |
| 422 | NO_FACE / MULTIPLE_FACES / FACE_TOO_SMALL | The photo must show exactly one clear, large enough face. |
| 422 | CONSENT_REQUIRED | SUBMIT_VIA_MIRA needs every finance consent set to true, and consents.providerName. |
| 422 | EKYC_NOT_CONFIGURED | Identity verification is not set up. Set it up in MIRA Business under Settings, Identity Verification. |
| 422 | FINANCE_PANEL_NOT_CONFIGURED | SUBMIT_VIA_MIRA needs a finance panel set up in MIRA Business. |
| 422 | INSUFFICIENT_CREDITS | The wallet that pays for these checks needs topping up. |
| 422 | DEALER_ONLY | A cash-sale DELIVERY needs a dealer key. |
| 429 | RATE_LIMITED | More than 500 requests in a minute on this key. |
| 503 | TEMPORARILY_UNAVAILABLE | Try again with the same Idempotency-Key. Nothing was created. |
Limits
- 500 requests a minute per key; beyond that, 429.
- Customer photos up to 5 MB, JPEG or PNG.
- List pages up to 100 journeys.
- Webhook responses within 10 seconds.