Transactions

Read the verification transactions recorded for your tenant. Transactions are read-only. A transaction is recorded when POST /api/v1/verifications reaches a pass or fail decision; some refused attempts record none (see the verification docs).

Note: No endpoint creates, changes or deletes a transaction. Each one also has a sealed audit record that only regulatory authorities can decrypt. It is never included in API responses.

The transaction object

FieldTypeDescription
idstringTransaction ID
createdAtstringISO 8601 timestamp
challengeTypestringWhat was checked. "age" for every verification the API makes
challengeDataobject{ "requiredAge": number }: the age the verification required
deviceIdstringDevice the verification is attributed to. Left out when there is none
verifiedBystringEmployee who attested a manual verification. Left out otherwise
verifyTypestring"pass" | "eID" | "manual"
tokenHashstringPass verifications only: hex SHA-256 of the Pass Token that was presented
resultstring"pass" | "fail"
failReasonstring | nullnull on a pass. On a fail: "underage" | "expired" | "invalid_signature" (unknown or revoked Pass Token) | "already_used" (Pass Token already consumed)
locationIdstringThe device's locationId at the time of the verification (see the device object). Left out when the device has none
posReferencestringThe posReference sent with the verification (receipt or basket ID). Left out when none was sent
livemodebooleanfalse for a transaction on a test tenant (see Test mode), true otherwise

Transactions have no updatedAt. Pagination and field formats follow the shared conventions.

GET/api/v1/transactions

List your tenant's transactions, newest first (always sorted by createdAt descending). Callers: service client (Bearer) and device (DPoP). Without limit, only the newest 100 matching transactions are returned, with no nextCursor or hasMore. Pass limit to page through all of them with nextCursor and hasMore (nextCursor is null on the last page). Each call reads a bounded amount of history, so a page can be shorter than limit, or empty, while hasMore is still true: keep following nextCursor until hasMore is false, and never treat a short page as the last one. A call without limit never returns an incomplete list: when it can't find 100 matches within the read budget (for example a posReference filter over a long history) it fails with 400, and you send limit and page with nextCursor, or narrow the date range. Only transactions in the tenant's current mode are listed: a live tenant never sees its test transactions, and a test tenant sees only test ones (see Test mode).

Headers

AuthorizationstringRequired

Bearer <access_token> (service client) or DPoP <access_token> (device). Requires transactions:read.

DPoPstringOptional

Device callers only: the DPoP proof for this request, including ath.

Query Parameters

deviceIdstringOptional

Only transactions attributed to this device. A malformed ID returns 400

verifiedBystringOptional

Only manual verifications attested by this employee. A malformed ID returns 400

locationIdstringOptional

Only transactions at this location. A malformed ID returns 400

verifyTypestringOptional

"pass" | "eID" | "manual"

resultstringOptional

"pass" | "fail"

posReferencestringOptional

Exact match on posReference

fromDatestringOptional

ISO 8601 date or date-time. Only transactions created at or after this moment

toDatestringOptional

ISO 8601 date or date-time. Only transactions created at or before this moment. A date-only value means midnight UTC at the start of that day, so 2026-05-06 excludes transactions made on 6 May; use 2026-05-07 or a full date-time to include it

limitintegerOptional

Page size, a positive integer, at most 5,000. Above 1,000 the call is meant to return the whole list at once, and fails with 400 if it can't be read in one go (see Errors); use 1,000 or less and follow nextCursor.

cursorstringOptional

nextCursor from the previous page

Examples

cURL

curl "https://abyrgverslun.is/api/v1/transactions?fromDate=2026-05-01&toDate=2026-05-07&limit=50" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response

{
  "data": [
    {
      "id": "n97e3r5t7y9u1i3o5p7a9s2d4f6g8h1j",
      "createdAt": "2026-05-06T10:31:12.044Z",
      "challengeType": "age",
      "deviceId": "k57a3m9qz4x8c1n2v6b0d5f7gh1j2k3l",
      "verifyType": "pass",
      "tokenHash": "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
      "result": "pass",
      "failReason": null,
      "locationId": "jh72m4q9x1c8n3v5b6z0k2d7f4g9t1ra",
      "posReference": "R-10482",
      "challengeData": { "requiredAge": 20 },
      "livemode": true
    },
    {
      "id": "n97f8g6h4j2k9l7z5x3c1v8b6n4m2q9w",
      "createdAt": "2026-05-05T16:47:38.210Z",
      "challengeType": "age",
      "deviceId": "k57a3m9qz4x8c1n2v6b0d5f7gh1j2k3l",
      "verifiedBy": "m17d4f6g8h2j3k5l7z9x1c3v5b7n9q2w",
      "verifyType": "manual",
      "result": "pass",
      "failReason": null,
      "locationId": "jh72m4q9x1c8n3v5b6z0k2d7f4g9t1ra",
      "challengeData": { "requiredAge": 18 },
      "livemode": true
    }
  ],
  "nextCursor": "n97f8g6h4j2k9l7z5x3c1v8b6n4m2q9w",
  "hasMore": true
}

Errors

  • 400 deviceId, verifiedBy or locationId is not a valid ID.
  • 400 limit is above 1,000 and the page can't be read in one call (a long date range with a posReference filter, or no filter at all). Narrow the date range, or use a limit of 1,000 or less and follow nextCursor.
  • 400 limit is not sent and 100 matches can't be found within the read budget (a long date range with a posReference filter). Send limit and page with nextCursor, or narrow the date range.
  • 401 Missing, invalid or expired token, or a device token sent as Bearer.
  • 403 The token lacks transactions:read.
  • 422 A query parameter failed validation: limit, verifyType, result, or a fromDate/toDate that isn't a parseable date.

Response format: Errors.

GET/api/v1/transactions/{id}

Read one transaction. Callers: service client (Bearer) and device (DPoP). The id is the transactionId a verification returns. To follow a verification you just made, you can also use GET /api/v1/verifications/{id}, which accepts transactions:write.

Headers

AuthorizationstringRequired

Bearer <access_token> (service client) or DPoP <access_token> (device). Requires transactions:read.

DPoPstringOptional

Device callers only: the DPoP proof for this request, including ath.

Examples

cURL

curl https://abyrgverslun.is/api/v1/transactions/n97c2v4b6n8m1q3w5e7r9t2y4u6i8o1p \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response

{
  "data": {
    "id": "n97c2v4b6n8m1q3w5e7r9t2y4u6i8o1p",
    "createdAt": "2026-05-06T10:33:40.517Z",
    "challengeType": "age",
    "deviceId": "k57a3m9qz4x8c1n2v6b0d5f7gh1j2k3l",
    "verifyType": "pass",
    "tokenHash": "3e23e8160039594a33894f6564e1b1348bbd7a0088d42c4acb73eeaed59c009d",
    "result": "fail",
    "failReason": "already_used",
    "locationId": "jh72m4q9x1c8n3v5b6z0k2d7f4g9t1ra",
    "challengeData": { "requiredAge": 20 },
    "livemode": true
  }
}

Errors

  • 401 Missing, invalid or expired token, or a device token sent as Bearer.
  • 403 The token lacks transactions:read.
  • 404 No transaction with this ID in your tenant: unknown, malformed, or another tenant's.

Response format: Errors.