Skip to main content
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.

Standard pricing

Card issuance costs 3 USD, plus 0.2% of the initial card balance. The minimum initial balance is 10 USD, excluding fees. Funding 10 USD therefore requires 13.02 USD from the company balance. Percentage fees are rounded up to the nearest cent. Individual company tariffs may differ. Always request a quote; its amount is the balance added to the card, fixedFee is the issuance charge, percentageFee is the funding charge, and total is the amount reserved from the company account. The separate card-account deposit fee is 1.5%, deducted only when funding the card account. It is not charged again when funding a card.

Before you start

Complete individual or corporate verification before creating any API key. Then 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.