# Card Tokens

[API Documentation](/api/card-token/card-token-object)

When a card is added to a digital wallet (Apple Pay, Google Pay, Samsung Pay) or stored as a card-on-file with a
merchant, a card token is created that represents the card's presence in that wallet or merchant system. Card tokens
are network-level tokens provisioned through the card networks' tokenization services (e.g., Visa Token Service).

Tokens are created by the network provisioning flow, not through the API — there is no create endpoint. Column
provides full visibility into the token lifecycle, allows your platform to control provisioning decisions through
real-time webhooks, and lets you pause, reactivate, or deactivate tokens through the API.

## Token Types

| Type ::min     | Description                                                                     |
| -------------- | ------------------------------------------------------------------------------- |
| `wallet`       | A token provisioned into a digital wallet (Apple Pay, Google Pay, Samsung Pay). |
| `card_on_file` | A token stored by a merchant for recurring or future payments.                  |

## Wallet Types

| Wallet ::min  | Description  |
| ------------- | ------------ |
| `apple_pay`   | Apple Pay.   |
| `google_pay`  | Google Pay.  |
| `samsung_pay` | Samsung Pay. |

## Provisioning Decisioning

Column can send a real-time webhook to your platform when a card token provisioning request is received, allowing
you to approve, decline, or require additional cardholder verification before a token is activated.

When a provisioning request passes Column's own checks (for example, the card exists and is active), Column sends a
webhook to the endpoint registered for the `decision.issuing.card_token` event type and waits up to 3 seconds for a
response. The request body contains the card token under the `card_token` field, and carries the same
`Column-Signature` header used by other webhooks to validate that the request originated from Column.

Your platform responds with one of the following `decision` values:

| Decision ::min | Description                                                       |
| -------------- | ----------------------------------------------------------------- |
| `approve`      | The token provisioning is approved.                               |
| `decline`      | The token provisioning is denied.                                 |
| `step_up`      | Additional cardholder verification is required before activation. |

If no endpoint is registered for the event type, or no response or an invalid response is received within the
deadline, Column declines the provisioning request.

The outcome of a provisioning decision is recorded on the card token in the `provisioning_decisioning_details`
field, including the decision, who made it (`column` or `platform_owner`), and a rejection reason when declined. The
field can be empty for requests that Column declines before a provisioning decision is made.

See [Real-time Decisioning](/card-issuing/card-real-time-decisioning) for more details on the overall decisioning
flow, including webhook endpoint setup.

## Cardholder Verification

When a token provisioning request requires additional cardholder verification (through a `step_up` decision response
or network requirements), Column supports a passcode-based verification flow. The token moves to the `stepping_up`
status while the cardholder's verification method is selected.

Your platform is responsible for delivering the one-time passcode to the cardholder. When the passcode is sent, the token
moves to `pending_authentication` (firing `issuing.card_token.pending_authentication`), and Column sends an
`issuing.card_token.send_passcode` webhook containing the card token fields along with the fields below. The card token in
this payload therefore has the status `pending_authentication`.

| Field ::min        | Description                                                                                        |
| ------------------ | -------------------------------------------------------------------------------------------------- |
| `otp_value`        | The one-time passcode to deliver to the cardholder.                                                |
| `otp_method_type`  | The delivery method: `sms` or `email`. Empty when Column cannot resolve the delivery method.       |
| `otp_phone_number` | The phone number (E.164) to deliver the passcode to. Present only when `otp_method_type` is `sms`. |
| `otp_email`        | The email address to deliver the passcode to. Present only when `otp_method_type` is `email`.      |

The token remains in `pending_authentication` until the network reports the result of the verification, and moves to
`active` once the cardholder is verified.

## Device Binding

Device binding associates an existing token with a new device. It follows the same verification flow as initial
provisioning: real-time decisions use the `decision.issuing.card_token.device_binding` event type, and passcode
delivery and verification use the `issuing.card_token.device_binding.*` events listed below.

## Managing Tokens

Active tokens can be temporarily paused, and paused tokens reactivated, using the
[pause](/api/card-token/pause-card-token) and [activate](/api/card-token/activate-card-token) endpoints. While a
token is paused, authorizations with the token are declined.

A token that is not already deactivated can be deactivated using the
[deactivate](/api/card-token/deactivate-card-token) endpoint. Deactivated tokens cannot be reactivated through the API.
If the network later sends a new provisioning request for a previously deactivated token, Column resets it to
`pending_activation` and the normal provisioning flow runs again.

Tokens also follow the lifecycle of their card:

- Deactivating a card with `deactivate_card_tokens` set to `true` deactivates its tokens. Without it, deactivating a card
  that has tokens which are not deactivated fails with a 400 error.
- Closing a card account with `deactivate_cards_and_card_tokens` set to `true` deactivates its cards and their tokens.
- Renewing a card keeps its tokens alive (the card number is unchanged) and re-links them to the new card, firing an
  `issuing.card_token.card_changed` event.
- Replacing a card deactivates its tokens.

## Statuses

| Status ::min             | Description                                                                                                             |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `pending_activation`     | The token has been requested but is not yet active. May be awaiting a provisioning decision or cardholder verification. |
| `stepping_up`            | The token requires additional cardholder verification and a passcode has not been sent yet.                             |
| `pending_authentication` | A passcode has been sent to the cardholder and the token is awaiting verification.                                      |
| `activation_denied`      | The token provisioning request was denied.                                                                              |
| `active`                 | The token is active and can be used for transactions.                                                                   |
| `paused`                 | The token is temporarily suspended.                                                                                     |
| `deactivated`            | The token has been deactivated.                                                                                         |

## Events

Card token event payloads contain the [card token object](/api/card-token/card-token-object).

### Token Lifecycle Events

| Event ::min                             | Description                                                                 |
| --------------------------------------- | --------------------------------------------------------------------------- |
| `issuing.card_token.pending_activation` | A new token has been created and is pending activation.                     |
| `issuing.card_token.activated`          | The token has been activated.                                               |
| `issuing.card_token.paused`             | The token has been paused.                                                  |
| `issuing.card_token.deactivated`        | The token has been deactivated.                                             |
| `issuing.card_token.activation_denied`  | The token provisioning was denied.                                          |
| `issuing.card_token.card_changed`       | The underlying card for the token has changed (e.g., after a card renewal). |

### Token Authentication Events

| Event ::min                                 | Description                                                      |
| ------------------------------------------- | ---------------------------------------------------------------- |
| `issuing.card_token.step_up`                | Additional cardholder verification is required.                  |
| `issuing.card_token.send_passcode`          | A passcode needs to be sent to the cardholder for verification.  |
| `issuing.card_token.pending_authentication` | A passcode has been sent and the token is awaiting verification. |

### Device Binding Events

| Event ::min                                                | Description                                                               |
| ---------------------------------------------------------- | ------------------------------------------------------------------------- |
| `issuing.card_token.device_binding.step_up`                | Additional verification is required for device binding.                   |
| `issuing.card_token.device_binding.send_passcode`          | A passcode needs to be sent for device binding verification.              |
| `issuing.card_token.device_binding.pending_authentication` | A passcode has been sent for device binding and is awaiting verification. |
