Skip to main content
A checkout session groups the calls of one customer interaction at the point of sale: identifying the customer, then paying against their wallet. Each call carries the session id so the interaction is tracked as one record. You do not create or close a session directly today. The one session operation you call is identify: it attaches a customer identity to a session and returns their wallet context. The rest of this page documents that call, its request and response fields, and the states a session moves through.
A standalone entry point that opens or closes a session is not yet available. Today you attach identity to a session with the call below, and you settle by calling POST /v1/partner/payments. See Payments and redemption.

Session states

A session moves through four states:
  • OPEN: the session exists and carries an anonymous_session_id, but no identity is attached yet.
  • IDENTIFIED: a credential resolved the customer. The session now carries the customer’s wallet context.
  • AUTHORIZED: written only by a successful session payment. You never set this directly.
  • CLOSED: settled into a receipt of record.
  • ABANDONED: the interaction ended without settlement. A session that times out auto-abandons at its expiry.
The identify call moves a session from OPEN to IDENTIFIED. It accepts a session that is OPEN or already IDENTIFIED (a re-identify on an identified session is allowed and idempotent). A session that is CLOSED or ABANDONED cannot be identified and returns VALIDATION_ERROR. The session lifecycle runs identify, then settle, then close:

Attach identity to a session

POST /v1/partner/checkout/sessions/{id}/identify attaches a customer identity to an open session and returns their CustomerContext. It dispatches on a credential discriminated union (phone, card_fingerprint, short_code, provider_customer_id, or qr) and merges the session’s anonymous_session_id into the resolved customer (a one-way, idempotent merge).
This call never returns a debit token or payment token. Identity resolution and money movement are strictly separated. To charge a customer, call POST /v1/partner/payments with a payment credential. See Payments and redemption.

Request

This call is authenticated with a POS terminal JWT. Send exactly one credential block per call; credential_type is the discriminator.
required
Partner-generated UUID, the one dedup key. Stable for this one logical operation, 24h TTL. Same key plus same payload replays the original response; same key plus a different payload returns IDEMPOTENCY_KEY_REUSED (HTTP 422).
required
The checkout session id (UUID) to attach identity to. The session must be OPEN or IDENTIFIED. When you also send context.feddi_session_id, it must match this path value.
required
Request context. Carries merchant_id (UUID, required) and the optional branch_id, terminal_id, cashier_id, partner_session_id, and feddi_session_id. The merchant_id is enforced against the calling credential’s authority, not trusted as free text.
required
One credential block, discriminated by credential_type. One of phone, card_fingerprint, short_code, provider_customer_id, or qr. Set the matching value field: phone (E.164), provider_customer_id, card_fingerprint (masked-PAN hash), short_code (5-character wallet code), or qr (raw QR payload). The enabled set for your integration is in GET /v1/partner/capabilities under supported_identify_credential_types.
required
Disambiguate when the identity resolves to multiple wallet programs. Omit it on the first call; if the response is WALLET_PROGRAM_AMBIGUOUS, re-send with the chosen wallet_program_id.
required
Request metadata. Carries partner_request_id (UUID, your correlation id, never the dedup basis), api_version, and the optional occurred_at and sent_at timestamps.

Response

A 200 returns a CustomerContext. It never contains a debit token.
required
One of registered, pending_proof, not_found. registered is fully enrolled, balance readable and spendable. pending_proof is enrolled but not yet identity-verified; balance is visible but spend may be gated by the POS. not_found means no wallet user resolved for this credential under this enterprise, returned as HTTP 200 to distinguish it from a server error. Render a register CTA, not an error.
required
Opaque correlation id for this identity resolution. Persist it and echo it where a call accepts one.
The customer’s wallet_user_id. Null when resolution_state is not_found.
The wallet program binding. Null when resolution_state is not_found. An ambiguous match returns WALLET_PROGRAM_AMBIGUOUS (HTTP 422) rather than this field.
The canonical wallet_id (ledger row). Null when resolution_state is not_found or the customer’s wallet has not been created yet (no credits).
Customer display name. Null when unknown.
Loyalty tier badge label. Null when the program has no tiering.
Wallet balance breakdown, or null when resolution_state is not_found. Carries the two money classes and a per-grant breakdown.
The balance object splits the wallet into two money classes. See Money: actual vs promotional for the full model. The response meta block carries two opaque fields. data_completeness_score is an opaque integer Feddi may use internally; no action required. decision_trace_id is an opaque correlation id; persist and echo it where a call accepts one.

Example

Errors

Inspect error.code, not the HTTP status, for programmatic branching. See Idempotency and errors for the full catalog.

Invariants

Hold these when you render the result:
  • Identify never returns a debit token. To debit, call POST /v1/partner/payments with a payment credential.
  • not_found is HTTP 200, not 404, with resolution_state: not_found. Render a register CTA, not an error.
  • A card_fingerprint link is probationary until the phone is verified. A masked-PAN collision never auto-acts on money.
  • Identify never releases a LOCKED promotional grant on its own. Promo release stays gated on a verified identity plus the claim flow. See PENDING_PROOF and promo release.
  • A customer’s balance is scoped per merchant.
For a balance-check panel with no active session, use GET /v1/partner/customers/lookup or the standalone POST /v1/partner/identify instead. See Customers and identification.

Next

Money: actual vs promotional

The two-class balance model that runs through every endpoint.

Identity and credentials

The credential types and how a call resolves who the customer is.

Payments and redemption

The promo-first wallet-debit endpoint you settle against.

Make your first payment

The identify-to-pay loop, worked end to end.