ROOKDocs
5 min readUpdated August 2026

Digital Wallets & Tokenization

Push-provision cards into Apple Pay, Android Pay, and Samsung Pay, then manage the network tokens those wallets create. Token objects return last_four and DPAN last four only, never PAN or CVV.

In-app provisioning

From your mobile app, collect wallet SDK material and call POST /v1/cards/{card_id}/provision.

digital_wallet Body SDK consumes
APPLE_PAY certificate, nonce, nonce_signature from PassKit provisioning_payload as PKAddPaymentPassRequest
GOOGLE_PAY digital_wallet only provisioning_payload as an opaque payment card (OPC)
SAMSUNG_PAY digital_wallet only provisioning_payload as an OPC

The response is operational (object is card_provision). It is not a persisted tokenization. The wallet talks to the network; the token appears on GET /v1/tokenizations after the network confirms.

{
  "object": "card_provision",
  "card_id": "0c4e8f16-2a7b-4d93-b5e1-8f3a6c9d0142",
  "digital_wallet": "APPLE_PAY",
  "provisioning_payload": "eyJwYXlsb2FkIjoiLi4uIn0"
}

Send Idempotency-Key. A retried provision with the same key returns the original payload instead of minting a second one.

Web provisioning

POST /v1/cards/{card_id}/web-provision is the browser equivalent (Apple Pay on the Web). The body is { "digital_wallet": "APPLE_PAY" }. The response is a compact jws plus opaque state. Pass both to the wallet JavaScript API. Echo state unchanged; do not parse it.

{
  "object": "card_web_provision",
  "card_id": "0c4e8f16-2a7b-4d93-b5e1-8f3a6c9d0142",
  "digital_wallet": "APPLE_PAY",
  "jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ3ZWItcHJvdmlzaW9uIn0.signature",
  "state": "9c2e4a71-6d8b-4f03-b5e1-0a7c8d9f1246"
}

The JWS never contains PAN or CVV.

Token lifecycle

GET /v1/tokenizations lists tokens. Filter on card_id, wallet_id, status, and wallet (APPLE_PAY, GOOGLE_PAY, SAMSUNG_PAY). GET /v1/tokenizations/{tokenization_id} returns the snapshot, including token_requestor_name, device, last_four, dpan.last_four, and events[].

status Meaning
INACTIVE Created at the network; ineligible to authorize until activated.
PENDING_ACTIVATION Waiting on the cardholder to complete wallet activation.
PENDING_2FA Waiting on an activation code (SMS or EMAIL).
ACTIVE Authorizes.
PAUSED Temporarily declines wallet presentations.
DEACTIVATED Terminal. Cannot be reversed.

Lifecycle actions are POST sub-resources. Each takes Idempotency-Key.

Call From To
POST .../activate INACTIVE, PENDING_ACTIVATION, PENDING_2FA ACTIVE
POST .../pause ACTIVE PAUSED
POST .../unpause PAUSED ACTIVE
POST .../deactivate any non-terminal DEACTIVATED
POST .../resend-activation-code PENDING_ACTIVATION, PENDING_2FA same status; new code

resend-activation-code body is { "channel": "SMS" } or { "channel": "EMAIL" }. The cardholder contact comes from the wallet wallet entity. Do not send a phone number or email in this body.

POST .../update-digital-card-art assigns art from GET /v1/digital-card-art. The art must match the token’s network and have is_enabled true.

Every status change emits tokenization.updated. Subscribe with a webhook subscription. payload is the Tokenization snapshot.

Digital card art

GET /v1/digital-card-art lists artwork the wallet can display. GET /v1/digital-card-art/{digital_card_art_id} returns network, is_enabled, description, and images (front, logo, icon) as HTTPS URLs. Those URLs are image assets, not PAN.

Tokenization Decisioning

Enroll an HTTPS URL with POST /v1/responder-endpoints and type TOKENIZATION_DECISIONING. Rook POSTs a tokenizationRequest callback to that URL when a cardholder adds a card to a wallet. Respond within 3 seconds with:

{
  "object": "tokenization_decision",
  "result": "APPROVED",
  "authentication_channels": null
}

result is APPROVED, DECLINED, or REQUIRE_ADDITIONAL_AUTHENTICATION. When stepping up, set authentication_channels to SMS and/or EMAIL:

{
  "object": "tokenization_decision",
  "result": "REQUIRE_ADDITIONAL_AUTHENTICATION",
  "authentication_channels": ["SMS", "EMAIL"]
}

The request body is device and wallet data (object is tokenization_request): digital_wallet, wallet.wallet_id, device.device_id, device.device_type, device.ip_address, and device.location. It never includes PAN or CVV.

Timeout and fallback

If your endpoint does not return HTTP 200 with a valid decision body within 3 seconds (including connection errors, TLS failures, 5xx, and malformed JSON), Rook declines the provisioning request. Prefer failing closed: keep the responder fast and reachable.

Signature

Callbacks are signed with the same HMAC-SHA256 scheme as Event deliveries. Retrieve the secret with GET /v1/tokenization-decisioning/secret. Use the entire whsec_... string as the key.

Header Value
Rook-Timestamp Unix time in seconds when the signature was computed.
Rook-Signature v1=<hex>. Multiple v1= values may be comma-separated during rotation.

Signed material is {timestamp}.{raw_body}. Reject a callback whose timestamp is more than 300 seconds from the current time. After POST /v1/tokenization-decisioning/secret/rotate, the previous secret remains valid for 24 hours.

Getting Started → Webhook signing covers the same scheme.

A program may enroll at most one TOKENIZATION_DECISIONING responder. DELETE /v1/responder-endpoints/{responder_endpoint_id} stops callbacks immediately.

Was this page helpful?