BEXO / Developers
BUILD WITH BEXO / API REFERENCE

Terminal verification API

A reader sends a card or QR observation. BEXO returns a tenant-scoped decision using the server’s current entitlement evaluation.

Reference edition 2026-10-19 • Selected public contract
NFCPOSverificationreaderbatch

Bind a key and a registered device

POS v1 requires a scoped tenant integration key with verify:write plus X-Terminal-Serial for a reader registered to the same tenant. An owner token is not accepted as a device key. A revoked or decommissioned reader must not continue verification.

Handle decisions separately from HTTP

ResponseYour client should
200, verified=true, decision=allowDisplay the allowed result and perform only the access action approved for this integration.
200, verified=false, decision=denyDisplay the supplied reason and a clear assistance path. Do not retry a normal denial as if it were a network error.
401 / 403Stop automatic traffic and investigate credential, scope, approval or device state.
Timeout / 5xxShow an unavailable state. Follow your approved recovery procedure; do not infer permission.

Common reasons include active, grace, expired, suspended, member_not_found, no_membership_for_vendor and card_revoked_or_blocklisted. Handle unrecognized reason strings safely; do not infer access from human-readable text.

Clock and buffered synchronization

timestamp is optional observability input. The server’s clock is the authority when a tap is processed. Buffered requests are evaluated when synchronized; they are not proof that a person had valid access earlier. The batch endpoint processes items individually and reports successes and failures per item.

There is no documented idempotency key for POS taps or batches. Retrying can create duplicate log/usage records. Keep your own correlation record and confirm the supported duplicate-handling policy before automatic replay. Never treat offline buffering as authorization to unlock a gate.

Display only what is appropriate

Treat subscriber as nullable. Member names, photos and validity details are personal data, even when a response includes them. Keep the operational decision separate from disclosure consent; consult current member permissions before display, export or storage. Do not retain raw card identifiers in general logs.

billing records returned usage; it is not a quotation or a statement that your commercial agreement has changed. latencyMs is server processing time and excludes network/UI latency. X-Request-Id and logId help support investigate a request.

REQUEST / RESPONSE

Endpoint reference

Paths below include the API prefix. The OpenAPI server URL already includes /api.

GET/api/pos/v1/ping

Check a registered reader connection

Requires verify:write scope and a registered terminal identifier. Returns vendor, terminal and serverTime; also updates terminal telemetry.

Scoped integration keyHTTP 200

Parameters

NameLocationRequirement
X-Terminal-SerialheaderRequired. Registered reader serial in the same tenant as the integration key.

Request template

Set the API base to include /api. Replace path placeholders before running.

shell
curl --fail-with-body -X GET "$BEXO_API_BASE/pos/v1/ping" \
  -H "Authorization: Bearer $BEXO_INTEGRATION_KEY" \
  -H "X-Terminal-Serial: $BEXO_TERMINAL_SERIAL"

Response fields

FieldTypeDetails
statusstringonline.
vendorobjectSee the downloadable schema for nested fields.
terminalTerminalSee the downloadable schema for nested fields.
serverTimestringServer ISO time.
View full machine-readable contract ↗
POST/api/pos/v1/verify

Evaluate a card or QR tap

Requires verify:write and a registered reader in the same tenant. The server evaluates current entitlement using its clock. HTTP 200 with decision=deny is a valid business result, not a transport failure. Treat all subscriber data as private and enforce the member’s current disclosure permissions in your client.

Scoped integration keyHTTP 200

Parameters

NameLocationRequirement
X-Terminal-SerialheaderRequired. Registered reader serial in the same tenant as the integration key.

Request template

Set the API base to include /api. Replace path placeholders and prepare request.json from the body fields below before running.

shell
curl --fail-with-body -X POST "$BEXO_API_BASE/pos/v1/verify" \
  -H "Authorization: Bearer $BEXO_INTEGRATION_KEY" \
  -H "X-Terminal-Serial: $BEXO_TERMINAL_SERIAL" \
  -H "Content-Type: application/json" \
  --data @request.json

Request body

FieldTypeDetails
cardUidstringRaw card read, if using a registered NFC reader. Keep private.
qrPayloadstringAlternative QR payload. At least one of cardUid or qrPayload is required.
timestampstringOptional ISO time reported by the terminal. Server time controls entitlement.

Example request body

json
{
  "cardUid": "<CARD_UID_READ_BY_REGISTERED_READER>",
  "timestamp": "2026-10-19T09:00:00Z"
}

Response fields

FieldTypeDetails
verifiedRequiredbooleanAccess outcome; use alongside decision.
decisionRequiredstringOperational outcome.
allow · deny
decisionReasonRequiredstringReason such as active, expired, no_membership_for_vendor or member_not_found.
statusstringMembership/lookup status.
subscriberobject · nullableSee the downloadable schema for nested fields.
terminalobject · nullableSee the downloadable schema for nested fields.
billingobjectSee the downloadable schema for nested fields.
latencyMsintegerServer evaluation time.
timestampstringServer evaluation time.
logIdstring · nullableLog reference.
json
{
  "verified": false,
  "decision": "deny",
  "decisionReason": "member_not_found",
  "status": "not_found",
  "subscriber": null,
  "terminal": {
    "id": "11111111-1111-4111-8111-111111111111",
    "label": "Reception",
    "serialNumber": "<REGISTERED_TERMINAL_SERIAL>",
    "hardwareModel": "BEXO-POS-T1"
  },
  "billing": {
    "billedPaise": 50,
    "costRupees": 0.5,
    "costDisplay": "₹0.50"
  },
  "latencyMs": 18,
  "timestamp": "2026-10-19T09:00:00Z",
  "logId": "11111111-1111-4111-8111-111111111111"
}
View full machine-readable contract ↗
POST/api/pos/v1/batch-verify

Synchronize buffered tap requests

Accepts {taps:[…]}, a raw array, or a single tap. Prefer the taps object. Results are evaluated by the server at synchronization time; this is not offline authorization. Retries can create new log/usage entries because no batch idempotency key is documented.

Scoped integration keyHTTP 200

Parameters

NameLocationRequirement
X-Terminal-SerialheaderRequired. Registered reader serial in the same tenant as the integration key.

Request template

Set the API base to include /api. Replace path placeholders and prepare request.json from the body fields below before running.

shell
curl --fail-with-body -X POST "$BEXO_API_BASE/pos/v1/batch-verify" \
  -H "Authorization: Bearer $BEXO_INTEGRATION_KEY" \
  -H "X-Terminal-Serial: $BEXO_TERMINAL_SERIAL" \
  -H "Content-Type: application/json" \
  --data @request.json

Request body

FieldTypeDetails
tapsRequiredarraySee the downloadable schema for nested fields.

Response fields

FieldTypeDetails
processedCountintegerResults processed.
resultsarraySee the downloadable schema for nested fields.
View full machine-readable contract ↗
Build with a clear contract.

Configuration, approval and deployed behavior determine availability. Validate your own integration before release.

Review the launch checklist ↗

Reference source: b93a4d3 · Examples use synthetic data.