Payment Tokens
Every successful payment auto-creates a reusable token (pt_…). This page covers the read + revoke endpoints for tokens already on file. To create a token by importing an existing gateway token, see Tokenization.
Tokenize vs Payment Tokens
POST /tokenize— import an existing gateway-side token under a customer (used by integrators migrating off another processor).GET /customers/{external_customer_id}/payment-tokens— list cards already saved through normal checkout flows.POST /payment-tokens/{id}/deactivate— revoke a token so it can't be charged again.
None of these endpoints capture a card from scratch. A new card is always tokenized through a checkout session.
Token statuses
| Status | Meaning |
|---|---|
active | Eligible for POST /charge-token and for use on subscriptions. |
inactive | Revoked by the merchant or the customer. Cannot be charged. |
expired | Past expiry_month / expiry_year. Cannot be charged. |
A token also goes inactive automatically when the underlying gateway flags it as unusable (e.g., chargeback / fraud lock).
List saved cards for a customer
GET /api/v1/customers/{external_customer_id}/payment-tokens{external_customer_id} is the merchant-side customer id (your wp_users.ID, your Magento customer_id, your Shopify customer_gid). Genius Checkout maps it during the first checkout — storefront plugins do this automatically.
Response (200)
{
"data": [
{
"id": "pt_xyz789",
"brand": "visa",
"last4": "4242",
"expiry_month": "12",
"expiry_year": "2030"
}
]
}If the customer has never paid through Genius Checkout, the response is {"data": []} (200, not 404) so storefront UIs can render the saved-card section unconditionally.
The encrypted token is never returned — use the id (pt_…) to reference the token in POST /charge-token or POST /subscriptions.
Deactivate a token
POST /api/v1/payment-tokens/{external_id}/deactivateIdempotent — calling it on an already-inactive token returns 200 with the current state. Use this when:
- A customer cancels their subscription on your merchant side and you want to revoke the saved card.
- A fraud signal on your end means the card should no longer be billable.
- You're cleaning up after account-deletion / right-to-erasure flows.
Response (200)
{
"id": "pt_xyz789",
"status": "inactive",
"brand": "visa",
"last4": "4242"
}Code samples
# Render a saved-card picker on your storefront
curl -H "Authorization: Bearer $GC_API_KEY" \
"https://app.geniuscheckout.com/api/v1/customers/wp_user_42/payment-tokens"// Node — revoke after a subscription cancel
await fetch(`https://app.geniuscheckout.com/api/v1/payment-tokens/${tokenId}/deactivate`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.GC_API_KEY}`,
'Idempotency-Key': crypto.randomUUID(),
},
})# Python — list a customer's saved cards
import requests
r = requests.get(
f"https://app.geniuscheckout.com/api/v1/customers/{external_id}/payment-tokens",
headers={"Authorization": f"Bearer {GC_API_KEY}"},
)
cards = r.json()["data"]Security notes
- API keys are scoped to a single merchant. A request with one merchant's key can never see or revoke another merchant's tokens — cross-merchant lookups return
data: []or 404, never the existence of the resource. - Saved cards are never exposed in browser-facing code. Storefront plugins fetch the list from PHP / server-side, then render only
{id, brand, last4, expiry_*}to the page. The encrypted token stays on the GC platform.
Next
- Tokenization — charge a saved card with
POST /charge-token - Subscriptions — bind a token to a recurring schedule
