Skip to main content
Every route is nested under an identity. {identity} accepts an idn_… id or the identity’s name. An identity may hold any number of cards. A card is prepaid: bought once for load_micro_usd, never reloaded. Amounts are integer micro-USD (1 USD = 1000000). An agent reaches a card through the identity its session selected; there is no card-to-agent assignment to manage.
On a deployment with no card issuer bound, quoting, issuing, retrying and revealing answer 501 feature_not_configured before any credit moves; reads return what the identity already holds.

The card object

status is one of pending_payment, issuing, active, failed, cancelled, refunded. This object never carries a number, PIN, CVV or redemption link — those live only in the credential reveal.

List cards

GET /v1/identities/{identity}/cards — scope agents:read A paginated list of card objects. Filter with ?status=active.

Price a load

POST /v1/identities/{identity}/cards/quote — scope agents:read
price_micro_usd is what issuing will debit from credits — the load plus the issuer’s fee. A load outside the bounds answers validation_failed. Zero side effects.

Issue a card

POST /v1/identities/{identity}/cards — scope billing:write
The price is debited from the organization’s credits before the issuer is asked; a short balance answers 402 insufficient_credits and nothing is ordered. Answers 201 with the card in status issuing (the issuer is still fulfilling; read it again) or active. If the issuer refuses the order the card is failed with a provider-neutral failure_reason, its debit is held, and retry or refund settles it. Honours Idempotency-Key; the same key replays the same card without a second debit.

Read a card

GET /v1/identities/{identity}/cards/{card} — scope agents:read Reading an issuing card reconciles it with the issuer, so the status you see is current.

Reveal credentials

GET /v1/identities/{identity}/cards/{card}/credentials — scope billing:write
The only route that answers a card_credentials object. Every reveal writes an audit event (card.credentials_revealed — the event names the card, never the credential) and the response is Cache-Control: no-store. A card that is not active, or that the caller cannot see, answers 404 not_found — never a 403 that confirms it exists.

Lifecycle

POST /v1/identities/{identity}/cards/{card}/retry — scope billing:write — re-runs issuance from failed, reusing the held debit. POST /v1/identities/{identity}/cards/{card}/cancel — scope billing:write — marks an active card cancelled. The prepaid balance stays on the card. POST /v1/identities/{identity}/cards/{card}/refund — scope billing:write — returns the credits of a pending_payment or failed card and marks it refunded. A lifecycle action from any other status answers 409 state_conflict. A prepaid card has no top-up: buy another card.

Transactions

GET /v1/identities/{identity}/cards/{card}/transactions — scope agents:read POST /v1/identities/{identity}/cards/{card}/transactions — scope sessions:write
Logging a spend increments spent_micro_usd and is refused (validation_failed) when it would exceed the load. A prepaid card has no live authorization feed; this ledger is what the identity and its agents record. The list is paginated (limit default 50, max 200).

Errors

insufficient_credits before any issuer call; validation_failed for a load outside the quote’s bounds or an over-load spend; state_conflict for a lifecycle action from the wrong status; not_found for the credentials of a card that is not active; feature_not_configured. See Errors.