Skip to main content

Issuing a physical card

Get an embossed card delivered to the cardholder. There are two ways to ask for one, and the card behaves the same afterwards.

Before you begin​

You'll need:

  • Everything required to issue a virtual card, including an address on the cardholder and kyc_status: approved.
  • Physical card issuance enabled for your program. A program that doesn't issue physical cards refuses the request with unsupported_form_factor.
  • To request plastic for a card you already hold, a program whose processor supports it. Where it doesn't, POST /v1/cards/{card_id}/request-physical isn't mounted and the path returns 404 — the same answer a misspelled URL gets. Probe for it when you integrate rather than at run time.

How it works​

A physical card follows the same statuses as a virtual card, and is activated with the same call.

  1. Ask for the card. Either of the two ways below. Issuing a physical card directly returns a new card, inactive, or pending while the processor accepts the application, and you get card.issued when it moves on. Requesting plastic for a virtual card keeps the same card and id.
  2. Wait for it to arrive. Manufacturing and delivery take days, and they happen outside the API.
  3. Activate it. Call POST /v1/cards/{card_id}/activate. On a card issued directly, the first call turns the card on and orders the plastic, and fires card.activated. Once the cardholder has the plastic, call it again to enable the card for use in person. Until then every authorization on the card is declined.

Two ways to ask for a card​

Request one for a virtual card​

If the cardholder already has an active virtual card and now wants it printed, use POST /v1/cards/{card_id}/request-physical. There is no request body: the card keeps the name and the delivery address you gave when you issued it.

curl -X POST "$ALETA_BASE_URL/v1/cards/card_01HX8ZQ2K4M7P9RSTVWXYZAB/request-physical" \
-H "Authorization: Bearer $ALETA_ACCESS_TOKEN" \
-H "Idempotency-Key: $(uuidgen)"
Response
{
"id": "card_01HX8ZQ2K4M7P9RSTVWXYZAB",
"object": "card",
"cardholder_id": "chd_01HX8ZQ2K4M7P9RSTVWXYZAB",
"account_id": "acct_01HX8ZQ2K4M7P9RSTVWXYZAB",
"form_factor": "physical",
"status": "active",
"currency": "SGD",
"embossed_name": "A TAN",
"fulfillment": {
"status": "pending"
},
"created_at": "2026-08-02T10:14:00Z"
}

form_factor is now physical and fulfillment.status is pending: the plastic has been ordered. Everything else is the same card — same id, same number, same balance. status is untouched too, so the card goes on spending online while the plastic is made.

Requesting plastic twice is refused with card_invalid_state, because the card is already physical by then. When the cardholder has the plastic, call POST /v1/cards/{card_id}/activate to enable it for use in person.

Issue one directly​

If the cardholder doesn't need a virtual card first, create the physical card with POST /v1/cards:

curl -X POST "$ALETA_BASE_URL/v1/cards" \
-H "Authorization: Bearer $ALETA_ACCESS_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"cardholder_id": "chd_01HX8ZQ2K4M7P9RSTVWXYZAB",
"account_id": "acct_01HX8ZQ2K4M7P9RSTVWXYZAB",
"form_factor": "physical",
"embossed_name": "A TAN",
"delivery_address": {
"line1": "350 Orchard Road",
"city": "Singapore",
"postal_code": "238868",
"country": "SGP"
}
}'

embossed_name and delivery_address are required here.

What physical issuance adds​

The name on the card​

A physical card has a name printed or embossed on it. Once the card has been produced, that name can't be changed. If it's wrong, you'll need a new card and another delivery.

The processor sets the character limit (at most 26 characters), and it's usually shorter than the limits on standard name fields. Long names may not fit, so ask the cardholder what they want printed on the card rather than automatically using their legal name. Your integration should also be prepared to shorten the value.

Addresses​

Physical cards involve two addresses, and they don't have to be the same.

The card is registered to the address on the cardholder record. The plastic is sent to the delivery_address you gave when you issued the card.

Both are fixed at issuance. POST /v1/cards/{card_id}/request-physical takes no body, so plastic goes to the address the card already carries and there is no way to redirect it on the way. Issuance is the only moment a delivery address can be set, which is why it's required on every card rather than only on a physical one. If the cardholder has moved since, issue a new card.

The exact address fields depend on the processor. Some require more than a street, city, postcode, and country, so leave enough room in your address model to support additional fields.

The API checks that the address is complete, but it doesn't verify that the address actually exists. For example, a well-formed address for a nonexistent house can still pass validation and only fail after the card is shipped.

For that reason, validate delivery addresses with an address service on your side before asking for the card.

Manufacturing and delivery​

Physical cards take days rather than seconds. Manufacturing and delivery are handled by the card processor and carrier, so there isn't an API call you can make to move the card from one stage to the next.

Tracking a card through production and shipping isn't available yet. See fulfillment and shipping tracking for what is planned. Until then, your application knows when the cardholder has the card, and that is when to activate it.

Activation​

Activation is a server-to-server call, the same one a virtual card uses. There is no hosted page and no URL to open:

curl -X POST "$ALETA_BASE_URL/v1/cards/card_01HX8ZQ2K4M7P9RSTVWXYZEF/activate" \
-H "Authorization: Bearer $ALETA_ACCESS_TOKEN" \
-H "Idempotency-Key: $(uuidgen)"

A physical card is activated in two steps. The first call turns the card on and orders the plastic. The second, made once the cardholder has the plastic, enables the card for use in person. Both return the card.

Don't make the second call before the cardholder has the card. The API can't tell whether a card has arrived, so a card enabled early can be used in person before it is in the cardholder's hands.

Common errors​

For the errors on issuing the card, see issuing a virtual card. A physical card adds these.

StatuscodeFix
422card_invalid_stateActivation: the card is pending, frozen or expired. Requesting plastic: the card isn't an active virtual card, or is already physical
422card_closedThe card is closed. Issue a new one
422card_already_activatedActivation: the card is already active and its plastic has been confirmed as received
422unsupported_form_factorThe program doesn't issue physical cards
404card_not_foundThe card doesn't exist, or belongs to another organization
502processor_unavailableThe processor couldn't turn the card on, order the plastic or enable it for use in person. Retry with the same Idempotency-Key