Talk to usGet started
Guides

The person's own card

A cardholder connects one of their own credit or debit cards once, behind a passkey on their phone. The agent pays with it after they approve each purchase there. Nothing is issued, nothing is prepaid, they keep their points.

Connect the card

POST /v1/cards/connect returns a one-hour, single-use link. Send it to the cardholder and never open it yourself. They open it in Safari or Chrome on the phone they will approve purchases with, type the card once, and lock it with a passkey. The card is encrypted on their device before it leaves the page; AgentPay never holds the number in clear and never stores the security code.

cURL
curl -X POST https://api.joomjoo.com/v1/cards/connect \
  -H "Authorization: Bearer $AGENTPAY_API_KEY"
200
{
  "connect_id": "6f1c...",
  "connect_url": "https://claim.joomjoo.com/add/6f1c...#...",
  "expires_at": "2026-11-03T15:00:00.000Z",
  "status": "open",
  "instructions": "Send the link to the cardholder. They open it in Safari or Chrome on the phone they will approve purchases with, type the card once, and lock it with a passkey. The security code is never stored. Then GET /v1/cards shows it with source \"own\".",
  "request_id": "req_a1b2c3"
}

Once connected, GET /v1/cards lists it first, with source: "own".

Pay with it

Pass the card's id as own_card_id on POST /v1/checkout. The run drives the merchant as usual and stops at the review with status needs_card_approval:

  • approval_url is the link the cardholder opens on their phone. They see the amount and the merchant, type the security code, and confirm with their passkey.
  • approval_expires_at is when the link stops working.
  • The same link arrives on the checkout.needs_card_approval event, with amount_display and card_last4.

confirm_pay cannot skip this approval. The bank's own check (3-D Secure) on a connected card is not cleared by AgentPay; the cardholder completes it on the agent's screen.

Remove it

DELETE /v1/cards/{id} removes a connected card and withdraws any purchase waiting on it. An issued card is closed with POST /v1/cards/{id}/close instead; the two are never mixed.

Connecting a card is switched on per account. Where it is not, POST /v1/cards/connect answers 503 own_card_unavailable.