Accept with a saved card
Once a customer has paid once, you have a card token you can reuse — no hosted page, no redirect, just a server-to-server charge.
After a customer completes their first successful payment, MintCash returns a card token in subsequent payment lookups. The token represents that saved card on that provider. Use it to charge the same customer again without redirecting them anywhere.
When to use it
- One-tap re-orders for returning customers
- Upgrades or upsells from inside your product
- Programmatic charges (no human in the loop)
- Pre-authorisations and post-auth captures
If the customer needs to see and confirm a card, use the HPP flow instead.
The flow
No redirect. The customer doesn't see anything until you tell them about it.
Implementation
The request shape is almost identical to the HPP flow — but you include cardToken and omit returnUrl:
const r = await fetch("https://sandbox.mintcash.me/payments", {
method: "POST",
headers: {
Authorization: `Basic ${btoa(`${publicKey}:${secretKey}`)}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
externalId: orderId,
amount: 1499,
currency: "USD",
cardToken: savedCardToken, // from a previous successful payment
customer: {
externalId: customerId,
},
}),
});
const { payment } = await r.json();payment.redirectUrl will be null. The payment proceeds directly to either succeeded or failed (sometimes via pending if the provider needs reconciliation).
Where the token comes from
Every payment that succeeds via the HPP flow returns a cardToken field on the resulting payment record:
{
"id": "pmt_...",
"status": "succeeded",
"amount": 49.99,
"currency": "USD",
"cardToken": "tok_01HXX...",
"card": {
"brand": "mastercard",
"last4": "0000"
}
}Store the token alongside your customer record. Card metadata (brand, last4, expiry) is non-sensitive — safe to display in your dashboard so the customer recognises which card you'll charge.
Tokens are merchant-scoped
A cardToken belongs to the merchant who created it. Trying to use another
merchant's token returns invalid_argument with code invalidCardToken. The
provider never returns the raw card details — that's by design.
What to test
- Charge with a valid token — should hit
payment.succeededdirectly - Charge with an unknown token —
400 invalid_argument(invalidCardToken) - Charge with an inactive/expired token — same error
- Provider network failure — should hit
503 unavailable(providerUnreachable) - Idempotent retry on the same
externalId— second call returns the original payment