Create Card
Card issuance sequence:
- Onboard Customer: Create the cardholder as a customer resource, if they don't already exist.
- Identity Verification: Trigger KYC/KYB for the customer. This is required before a card can be issued.
- Create the card: Call the create card endpoint, referencing the product and (where required) the customer and account.
- Listen to the
card.createdwebhook event to know when the card is ready. - Fetch the card and show non-sensitive details (masked PAN, last 4, status) by default.
- Use the reveal-token flow to securely retrieve the full PAN/CVV, only when the cardholder needs it.
1.) Onboard Customer:
Start by onboarding the customer the card will belong to. Refer to our guides for individual and business customer onboarding respectively.
2.) Identity Verification:
KYC (for individual customers) or KYB (for business customers) must be completed before a card can be created for the customer. See Individual Customer KYC and Business Customer KYB for details.
3.) Create Card
Once the customer is verified from the steps above, call the endpoint below to create a card.
| Method | Endpoint |
|---|---|
POST | /api/v1/cards |
curl --request POST \
--url https://api.getanchor.co/api/v1/cards \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'x-anchor-key: <API Key>' \
--data '
{
"data": {
"type": "Card",
"attributes": {
"description": "Operations expense card"
},
"relationships": {
"product": {
"data": {
"id": "product_123",
"type": "Product"
}
},
"customer": {
"data": {
"id": "customer_123",
"type": "Customer"
}
},
"account": {
"data": {
"id": "account_123",
"type": "Account"
}
}
}
}
}{
"data": {
"id": "card_123",
"type": "Card",
"attributes": {
"status": "PENDING",
"productName": "Virtual Expense Card",
"description": "Operations expense card",
"currency": "NGN",
"availableBalance": 0,
"ledgerBalance": 0,
"holdBalance": 0,
"pendingBalance": 0,
"maskedPan": "539983******1234",
"last4": "1234",
"expiryMonth": "12",
"expiryYear": "29",
"createdAt": "2026-07-17T09:30:00Z"
},
"relationships": {
"customer": {
"data": {
"id": "customer_123",
"type": "Customer"
}
},
"account": {
"data": {
"id": "account_123",
"type": "Account"
}
},
"product": {
"data": {
"id": "product_123",
"type": "Product"
}
},
"organization": {
"data": {
"id": "organization_123",
"type": "Organization"
}
}
}
},
"included": []
}A newly created card starts out
PENDING. Listen for thecard.createdwebhook, then fetch the card again before treating it as ready to use. The full PAN and CVV are never returned at creation, use the reveal-token flow in below to view them.
4.) Fetch Card by ID
| Method | Endpoint |
|---|---|
GET | /api/v1/cards/:cardId |
Sample Request and Response
curl --location 'https://apiv2.getanchor.co/card/api/v1/cards/17840266131572-anc_card' \
--header 'x-anchor-key: <API Key>'{
"data": {
"id": "1784031572-anc_card",
"type": "Card",
"attributes": {
"createdAt": "2025-07-14T10:56:53",
"last4": "9099",
"balance": {
"pending": 0,
"available": 000,
"hold": 000,
"ledger": 000
},
"expiryMonth": "07",
"description": "Tech 2 Spend",
"currency": "USD",
"billingAddress": {
"line1": "Tyra house",
"line2": "Tyra house",
"city": "Lekki",
"state": "Lagos",
"postalCode": "23401",
"country": "NG"
},
"expiryYear": "2030",
"productName": "VIRTUAL_PREPAID_TEST",
"status": "ACTIVE",
"updatedAt": "2026-07-14T10:56:58"
},
"relationships": {
"product": {
"data": {
"id": "17816077310944166442-anc_prd",
"type": "Product"
}
},
"organization": {
"data": {
"id": "16538589610-anc_og",
"type": "Organization"
}
},
"account": {
"data": {
"id": "1781751133-anc_acc",
"type": "DepositAccount"
}
},
"customer": {
"data": {
"id": "1782187182-anc_ind_cst",
"type": "Individual"
}
}
}
}
}5.) Retrieving Sensitive Card Details
Retrieving a card’s PAN, CVV, and expiry information is a secure two-step process:
- Generate a short-lived reveal token.
- Use the reveal token to retrieve the sensitive card details.
The reveal token is valid for a limited period and must only be used for the card for which it was generated.
Step 1: Generate a reveal token
Request a temporary reveal token for the card.
| Method | Endpoint |
|---|---|
POST | `/api/v1/cards/:cardID/reveal-token |
curl --location --request POST 'https://apiv2.getanchor.co/card/api/v1/cards/17840266131572-anc_card/reveal-token' \
--header 'x-anchor-key: <API Key>'{
"data": {
"token": "eyJvcmdhbml6YXRpb25JZCI6IjE2NTM0OTMxNTcyLWFuY19jYXJkVhbIjoxNzgQ.6CX9xVa-",
"expiresAt": "2026-07-20T16:53:31.356886550Z",
"expiresInSeconds": 300
}
}| Field | Description |
|---|---|
token | Short-lived JWT used to authorize the sensitive-details request. |
expiresAt | Exact date and time at which the reveal token expires. |
expiresInSeconds | Remaining token validity in seconds. In this example, the token is valid for five minutes. |
Step 2: Retrieve the sensitive card details
Use the reveal token as a JWT bearer token to authenticate the card-details request.
| Method | Endpoint |
|---|---|
GET | /api/v1/cards/:cardId/details |
curl --location 'https://apiv2.getanchor.co/card/api/v1/cards/1784072-anc_card/details' \
--header 'Authorization: Bearer <token>>' \
--header 'x-anchor-key: <API key>'{
"data": {
"id": "178401572-anc_card",
"type": "CardDetails",
"attributes": {
"cvv": "....3i0BoCODeZXa3i0BoCODeZXavp:Qk...",
"expiryMonth": "07",
"expiryYear": "2030",
"expiry": "07/30",
"pan": "...ev:d0RBKaNYZDghXxHH:A+//fB...."
},
"relationships": {
"card": {
"data": {
"id": "1784021572-anc_card",
"type": "Card"
}
}
}
}
}Token handling requirements:
- Generate a new reveal token whenever the cardholder requests sensitive details.
- Use the token only for the card identified by :cardID .
- Do not persist the reveal token in a database, browser storage, analytics system, or application logs.
- Do not place the token in a URL or query parameter.
- Do not send the user’s regular access token to the details endpoint in place of the reveal token.
- Discard the token immediately after the details request.
- If the token expires, generate a new token instead of retrying with the expired token.
- Do not automatically generate another token without confirming that the user’s session remains authorized.
Updated about 2 hours ago