Events
Read an event
GET https://api.xipid.org/events/{id}
One event of the last 30 days, as it was posted. After 30 days it is deleted, and the challenge holds the outcome.
Scope: any live key of the brand.
Limits: 1,000 requests a minute per key and 2,000 requests a minute per source address; every answer says what is left in X-RateLimit-Remaining, and a refusal when to come back in Retry-After.
Idempotency: a read, safe to repeat.
Changes: 2026-09-26: added.
Parameters
idXipID's id for the event.
Xip-VersionThe version to answer in; when absent, the version the brand's org is pinned to.
2026-09-26: The first version: challenges, subjects and events, and the signed outcome.
Answers
200 OK
The event.
Its headers: X-Request-Id, Xip-Version, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.
idtypeHow the challenge closed.
challenge.verified: The person approved and every check passed.challenge.check_failed: A check the policy asks for did not pass.challenge.declined: The person declined.challenge.expired: No decision came before the challenge expired.challenge.canceled: The brand canceled the challenge, or its text could not be sent.
api_versionA released version of the API, named by the day its contract was fixed.
2026-09-26: The first version: challenges, subjects and events, and the signed outcome.
created_atdataidbrand_idstatusWhere the challenge is in its life; the last five are final.
created: Made; the text with its link is not sent yet.sent: The text with the link went to the person's phone.opened: The person opened the link and is reading the request.approving: The person approved, and the checks the policy asks for are running.verified: The person approved and every check passed. Final.check_failed: A check the policy asks for did not pass. Final.declined: The person declined. Final.expired: No decision came beforeexpires_at. Final.canceled: The brand canceled it, or its text could not be sent. Final.
subjectidpairwise_idreferencetierHow far the person's identity is verified.
0: Their phone and email are verified.1: A selfie too, which keeps their reference face.2: A government document too.
requesttypeWhat the brand asks the person to approve.
wire: A wire transfer.beneficiary_change: A change to whom a payment goes.withdrawal: A withdrawal of funds.password_reset: A reset of a password.address_change: A change of address.other: Anything else; the title says what.
titlesummarymoneyamount_minorcurrency
counterpartyreferencerequested_at
policychecksliveness: The selfie is of a live person at the phone, not a photo or a recording.face_match: The selfie's face matches the person's reference face.
allow_declineallow_noteexpires_in_seconds
callbackurl
metadataagentidkeyversionnameorgname
credential_id
checkscheckA check the page runs before an approval counts.
liveness: The selfie is of a live person at the phone, not a photo or a recording.face_match: The selfie's face matches the person's reference face.
passedscoremodeThe liveness mode the vendor says ran.
movement_and_light: Colored lights flashed on the screen during the selfie.movement: No lights, for a device that asks for reduced motion; the vendor rates it the less accurate.
checked_at
checkA check the page runs before an approval counts.
liveness: The selfie is of a live person at the phone, not a photo or a recording.face_match: The selfie's face matches the person's reference face.
passedscoremodeThe liveness mode the vendor says ran.
movement_and_light: Colored lights flashed on the screen during the selfie.movement: No lights, for a device that asks for reduced motion; the vendor rates it the less accurate.
reasonWhy the check did not pass.
below_threshold: It scored under the threshold XipID holds it to.no_face: The vendor found no face to score.capture_failed: The selfie did not complete.reference_missing: The brand deleted the reference face while the challenge was open.
checked_at
consentagreed_atnotice_versionThe notice the person agreed to before the selfie, by its version.
request-selfie-2026-11-02: A request's selfie notice of November 2, 2026, for a brand that keeps no frames.person-selfie-2026-11-02: The notice of November 2, 2026, before the selfie that takes a person to Tier 1.request-selfie-frames-2026-11-02: A request's selfie notice of November 2, 2026, for a brand that keeps frames, which says so and that the brand may get them only if the request is disputed.
notetextprovider_message_idstatusWhat became of the text, as the channel reports it; the last three are final.
accepted: The provider took the text.queued: The provider holds the text before the carrier has it.sending: The text is on its way to the carrier.sent: The carrier has the text.delivered: The phone received the text. Final.undelivered: The carrier could not deliver the text. Final.failed: The provider could not send the text. Final.
error_code
created_atsent_atopened_atdecided_atexpires_at
{
"id": "01JD2RB7C9E1G3J5K7M9N1P3R5",
"type": "challenge.verified",
"api_version": "2026-09-26",
"created_at": "2026-11-19T18:06:41.090Z",
"data": {
"id": "01JD2R5W8Y3K6M9P2S5V8X1Z4B",
"brand_id": "01JD2R1A3C5E7G9J1K3M5N7P9Q",
"status": "verified",
"subject": {
"id": "01JD2R2B4D6F8H0J2K4M6N8P0Q",
"pairwise_id": "Vb3kQ9xR2mTz7LpW4nYc8d",
"reference": "acct_4417",
"tier": 1
},
"request": {
"type": "wire",
"title": "Wire to Ridgeline Fabrication",
"summary": "The first payment on invoice 2291.",
"money": {
"amount_minor": 4500000,
"currency": "USD"
},
"counterparty": "Ridgeline Fabrication",
"reference": "INV-2291",
"requested_at": "2026-11-19T18:04:00.000Z"
},
"policy": {
"checks": [
"liveness",
"face_match"
],
"allow_decline": true,
"allow_note": true,
"expires_in_seconds": 600
},
"callback": {
"url": "https://acme-bank.example/xipid/outcomes"
},
"metadata": {
"branch": "downtown"
},
"checks": [
{
"check": "liveness",
"passed": true,
"score": 0.98,
"mode": "movement_and_light",
"checked_at": "2026-11-19T18:06:41.090Z"
},
{
"check": "face_match",
"passed": true,
"score": 0.99,
"checked_at": "2026-11-19T18:06:41.090Z"
}
],
"text": {
"status": "delivered"
},
"created_at": "2026-11-19T18:04:00.512Z",
"sent_at": "2026-11-19T18:04:01.204Z",
"expires_at": "2026-11-19T18:14:00.512Z",
"consent": {
"agreed_at": "2026-11-19T18:06:12.377Z",
"notice_version": "request-selfie-2026-11-02"
},
"opened_at": "2026-11-19T18:05:30.861Z",
"decided_at": "2026-11-19T18:06:41.090Z"
}
}
Errors
json_invalid, 400: The request body is not valid JSON.parameter_invalid, 400: The request contains invalid parameters.parameter_unknown, 400: The request contains a parameter this route does not take.version_invalid, 400: Xip-Version names no released version of this API.authentication_required, 401: Authentication is required.authentication_failed, 401: The credential is invalid, expired or revoked.insufficient_scope, 403: The credential does not allow this operation.resource_not_found, 404: No such resource.content_too_large, 413: The request body is larger than this route accepts.media_type_unsupported, 415: This route does not accept that Content-Type.rate_limit_exceeded, 429: Too many requests; try again later.internal_error, 500: Something went wrong on our side.service_unavailable, 503: The service is temporarily unavailable.