APG PayAPG Paydocs

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.

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

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

Request
curl -X GET "https://api.tst.au.apgpay.dev/bezel/issuer-transactions/<useIssuerTransactionIdFromSeed>" \
  -H "Authorization: Bearer $API_SECRET_KEY"
A refund on an issued card is read here, not at /refunds. /refunds is the acquiring collection. An issuing refund's only address is the refunds array on the issuer transaction it belongs to.
Capturing or refunding can answer with a disagreement rather than a change. 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.

Request
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"
}'