{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
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
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
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.