Live card issuance is not yet enabled for general access. Use an approved sandbox environment. Publishing this guide does not activate live credentials or the production API.
Before you start
Create a sandbox API key in Developers with holders:write, holders:read, services:read, cards:read, cards:write, and operations:read. Keep the key on your server. Obtain your approved API base URL from Plane; the production address is https://business.planewallet.org.
Set PLANE_API_BASE to that base URL and PLANE_API_KEY to your key. All examples below run from your backend.
1. Fund the sandbox
This endpoint only changes a test balance. It cannot credit a live account.
2. Create a cardholder
Save the returned id as HOLDER_ID. Sandbox holders are verified automatically; this is not a live KYC decision. An external ID must be unique within your company and environment. Holder creation does not use an idempotency header: after an uncertain response, look up the holder before creating another.
3. Select a product and quote
Read GET /api/v1/products. Choose a product with kind: "card" and the issue capability. Respect its minimum and maximum. The sandbox product is virtual-usd.
The response separates amount, fee, and total. Copy total exactly into expectedTotal. Do not hardcode a fee; company pricing can differ.
4. Submit once
Replace HOLDER_ID and QUOTED_TOTAL before sending. Persist the idempotency key and returned operation id in your database. Retrying an uncertain request must use the same key and body.
5. Confirm the result
Read GET /api/v1/operations/{id} until the status becomes completed or failed, or handle an operation.completed webhook. A completed issuance contains result.cardId. Retrieve the masked card through GET /api/v1/cards.
queued, processing, and provider_pending are not successful issuance. manual_review requires reconciliation; do not create a replacement order. See operation lifecycle and card details.