Tutorial: Request and enroll a physical card
End-to-end flow for issuing a physical Cardda card to a user, from "approve the request" to "the user holds the plastic in their hand and the card is associated to their account".
The flow:
- The user (or an admin) creates a
card_issuing_request. - An admin approves it.
- Cardda mints a virtual card immediately and dispatches a physical card to the shipping address.
- When the physical card arrives, the user activates it from the dashboard, which calls
confirm_card.
1. Create the request
curl -X POST 'https://api.cardda.com/v1/card_issuing_requests' \
-H "Authorization: Bearer $API_KEY" -H "company-id: $COMPANY_ID" \
-H "Content-Type: application/json" \
-d '{
"user_id": "USER_UUID",
"kind": "physical",
"shipping_address": {
"street": "Av. Apoquindo 4501",
"city": "Las Condes",
"region": "Santiago",
"postal_code": "7550000",
"country": "CL"
},
"spending_limit": { "amount": 500000, "currency": "CLP", "period": "monthly" },
"label": "Sales — Maria Perez"
}'{
"id": "request-uuid",
"status": "pending_approval",
"user_id": "USER_UUID",
"kind": "physical",
...
}2. Approve
Approval requires a company member with cards.approve permission (check via GET /v1/permissions).
curl -X PATCH 'https://api.cardda.com/v1/card_issuing_requests/REQUEST_ID/approve' \
-H "Authorization: Bearer $API_KEY" -H "company-id: $COMPANY_ID"To deny instead:
curl -X PATCH 'https://api.cardda.com/v1/card_issuing_requests/REQUEST_ID/decline' \
-H "Authorization: Bearer $API_KEY" -H "company-id: $COMPANY_ID" \
-H "Content-Type: application/json" \
-d '{ "reason": "Out of policy — requested limit exceeds department cap" }'After approval, Cardda creates a vendor_card. The status moves through:
vendor_card.status | Meaning |
|---|---|
pending_issue | Cardda is talking to the issuer (PLH / Pomelo / Increase). |
active_virtual | Virtual card is usable; physical card is being printed/shipped. |
shipped | Physical card mailed; tracking number available on shipping_metadata. |
active | Physical card activated and in use. |
closed | Card revoked. |
3. Track shipping
curl 'https://api.cardda.com/v1/vendor_cards/VENDOR_CARD_ID' \
-H "Authorization: Bearer $API_KEY" -H "company-id: $COMPANY_ID"{
"id": "vendor-card-uuid",
"status": "shipped",
"shipping_metadata": {
"carrier": "Chilexpress",
"tracking_number": "CL-12345678",
"estimated_delivery": "2026-05-03"
},
"last4": "4242",
...
}4. Activation by the cardholder
When the physical card arrives, the cardholder confirms their identity by sending the card's last 4 digits and CVV. Your front-end posts this to:
curl -X PATCH 'https://api.cardda.com/v1/vendor_cards/confirm_card' \
-H "Authorization: Bearer $API_KEY" -H "company-id: $COMPANY_ID" \
-H "Content-Type: application/json" \
-d '{
"vendor_card_id": "vendor-card-uuid",
"last4": "4242",
"cvv": "123"
}'After this call, status flips to active and the card can be used in person.
Set / change the PIN
curl -X PATCH 'https://api.cardda.com/v1/vendor_cards/VENDOR_CARD_ID/pin' \
-H "Authorization: Bearer $API_KEY" -H "company-id: $COMPANY_ID" \
-H "Content-Type: application/json" \
-d '{ "pin": "0420" }'Retrieve sensitive details (PAN / CVV) for a TPV widget
For PCI compliance, Cardda never returns the full PAN through the regular GET. Instead, you request a single-use, short-lived token and exchange it on the issuer's TPV widget:
curl 'https://api.cardda.com/v1/vendor_cards/VENDOR_CARD_ID/retrieve' \
-H "Authorization: Bearer $API_KEY" -H "company-id: $COMPANY_ID"{
"tpv_token": "ey...",
"tpv_url": "https://tpv.plh.com/widget?token=ey...",
"expires_at": "2026-04-29T18:05:00Z"
}Embed tpv_url in an iframe — the cardholder sees their PAN and CVV without your servers ever touching them.
Common pitfalls
- Wrong country in shipping address. Cardda issues in CL, MX, and PE. An address in another country is rejected at the
approvestep. spending_limitsmaller than a single legitimate purchase. The card declines silently at the merchant. Use theperiod: monthlysemantics with reasonable headroom.- Cardholder does not have a verified phone. PLH-issued cards require the user's phone to be verified for SMS step-up. Check
users.phone_verifiedbefore submitting the request.
Related
- Card Allocations — recurring funds top-up
- API reference: vendor_cards
- Errors
Updated 1 day ago
