Cards
Issue a virtual card, authorise and capture
Create a card the platform issues, then follow what happens when someone spends on it.
Everything else on this API is the acquiring side: you take money from someone else's card. This is the mirror, the platform issues the card and you watch money leave it.
That mirroring is the thing to hold on to. Payments, refunds and disputes are acquiring; issuer transactions carry their own refunds and disputes, on the card you issued.
A virtual card exists as data, there is no plastic and no shipping step.
curl -X POST "$VAULT_BASE_URL/cards" \
-H "Authorization: Bearer $API_PUBLISHABLE_KEY" \
-H "Content-Type: application/json" \
-d '{
"loanId": "<useLoanIdFromSeed>",
"spec": {
"cardUser": {
"name": "Priya Raman",
"emailAddress": "priya.raman@example.com",
"phoneNumber": "+61412345678",
"type": "CardUserAttributes"
},
"creator": "ops-user-114",
"validFrom": "2026-01-01T00:00:00Z",
"validTo": "2027-01-01T00:00:00Z",
"limits": null,
"usage": null,
"currencies": [
"AUD"
],
"metadata": null,
"type": "CardSpecAttributes"
},
"type": "CardCmdCreateMastercard"
}'The full number and CVV are not on the ordinary read. Card data comes back only through the encrypted read, and only to a caller entitled to it.
curl -X GET "https://api.tst.au.apgpay.dev/bezel/cards/<useCardIdFromStep1>" \
-H "Authorization: Bearer $API_SECRET_KEY"An issuer transaction appears when the card is used. It carries the acquiring merchant, the settlement merchant, and, embedded, in full, its refunds and disputes.
curl -X GET "https://api.tst.au.apgpay.dev/bezel/issuer-transactions/<useIssuerTransactionIdFromSeed>" \
-H "Authorization: Bearer $API_SECRET_KEY"/refunds. /refunds is the acquiring collection. An issuing refund's only address is the refunds array on the issuer transaction it belongs to.PATCH /issuer-transactions returns an outcome: ItxnUpdateOutcomeChanged carries the transaction as it now stands, and ItxnUpdateOutcomeDiscrepancy means the network disagreed about the amount and the platform recorded that instead. Switch on type, a discrepancy is not an error and not a failure to retry, it is a record to go and read.Cancelling stops further authorisations and CardUpdateActivate lifts it, so this is reversible, which the old status field could not say clearly. OutOfLifetime follows from the dates and has no arm, because it was never something you could set.
curl -X PATCH "https://api.tst.au.apgpay.dev/bezel/cards/<useCardIdFromStep1>" \
-H "Authorization: Bearer $API_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "CardUpdateCancel"
}'