---
title: "Issue and manage cards"
description: "Create a customer, complete verification, issue a card, fund it, and withdraw funds."
---

# Issue and manage cards

This recipe takes an individual customer from creation through card issuance, funding, and withdrawal.

Before you start, identify the funded internal account that will back and fund the card. Every `POST` request in this recipe requires an `Idempotency-Key`. Use a new value for each operation, and reuse that value only when retrying the same operation with the same payload.

## Flow overview

```mermaid
sequenceDiagram
    autonumber
    actor Client
    participant API as Gravv API
    actor Customer

    Client->>API: Create customer and start verification
    API-->>Customer: Verification session
    Customer->>API: Complete verification
    Client->>API: Create backing account and activate cards
    alt Liveness or manual review required
        API-->>Client: pending_liveness or manual_review
        Client->>API: Poll application status
    else Application approved
        API-->>Client: approved
    end
    Client->>API: Issue card
    loop Until card is ready
        Client->>API: Retrieve card
        API-->>Client: Current card status
    end
    Client->>API: Fund or withdraw from card
    API-->>Client: Processing result
```

<Steps>
<Step title="Create the customer">

Create the individual customer who will own the card.

<RequestExample>
```bash title="Request"
curl --request POST \
  --url https://api.gravv.xyz/v1/customers \
  --header 'Api-Key: <API_KEY>' \
  --header 'Idempotency-Key: customer-<UUID>' \
  --header 'Content-Type: application/json' \
  --data '{
    "first_name": "Sarah",
    "last_name": "Johnson",
    "email": "sarah.johnson@example.com",
    "phone": "+14155552345",
    "type": "individual",
    "gender": "female",
    "date_of_birth": "1990-03-15",
    "address": {
      "address_line1": "123 Market Street",
      "city": "San Francisco",
      "postal_code": "94102",
      "state": "US-CA",
      "country": "US"
    }
  }'
```
</RequestExample>

<ResponseExample>
```json title="Response"
{
  "data": {
    "id": "9e3cccad-e9ae-47a0-81ee-063af0159310",
    "first_name": "Sarah",
    "last_name": "Johnson",
    "type": "individual",
    "status": "active"
  },
  "error": null
}
```
</ResponseExample>

Save `data.id` as the customer ID.

</Step>

<Step title="Complete customer verification">

Start KYC for the customer, then direct them to the returned verification URL. Wait for KYC to reach `completed` before continuing.

<RequestExample>
```bash title="Request"
curl --request POST \
  --url https://api.gravv.xyz/v1/customers/kyc/start \
  --header 'Api-Key: <API_KEY>' \
  --header 'Idempotency-Key: kyc-<UUID>' \
  --header 'Content-Type: application/json' \
  --data '{
    "customer_id": "9e3cccad-e9ae-47a0-81ee-063af0159310"
  }'
```
</RequestExample>

<ResponseExample>
```json title="Response"
{
  "data": {
    "status": "success",
    "web_url": "https://verify.gravv.xyz/websdk/p/example_token"
  },
  "error": null
}
```
</ResponseExample>

Use [KYC status](/api-reference/kyc/get-v1-customers-customer-id-kyc-status) or customer KYC webhooks to confirm completion.

</Step>

<Step title="Create the card's backing account">

Create the USD account that will back the customer's card.

<RequestExample>
```bash title="Request"
curl --request POST \
  --url https://api.gravv.xyz/v1/accounts \
  --header 'Api-Key: <API_KEY>' \
  --header 'Idempotency-Key: card-account-<UUID>' \
  --header 'Content-Type: application/json' \
  --data '{
    "currency": "USD",
    "type": "regular",
    "blockchain_network": "polygon",
    "label": "Sarah Johnson card account",
    "customer_id": "9e3cccad-e9ae-47a0-81ee-063af0159310"
  }'
```
</RequestExample>

<ResponseExample>
```json title="Response"
{
  "data": {
    "id": "5d9e677f-f071-4881-a861-7cdcebacd9d5",
    "customer_id": "9e3cccad-e9ae-47a0-81ee-063af0159310",
    "currency": "USD",
    "type": "regular",
    "status": "active"
  },
  "error": null
}
```
</ResponseExample>

Save `data.id` as the backing account ID.

</Step>

<Step title="Activate the card feature">

Activate `virtual_cards`. This creates the card application used for issuance.

<RequestExample>
```bash title="Request"
curl --request POST \
  --url https://api.gravv.xyz/v1/risk/features/activate \
  --header 'Api-Key: <API_KEY>' \
  --header 'Idempotency-Key: card-activation-<UUID>' \
  --header 'Content-Type: application/json' \
  --data '{
    "customer_id": "9e3cccad-e9ae-47a0-81ee-063af0159310",
    "feature_id": "virtual_cards",
    "provider_data": {
      "annual_remuneration": 75000,
      "estimated_monthly_limit": 2000,
      "ip_address": "192.0.2.10",
      "account_id": "5d9e677f-f071-4881-a861-7cdcebacd9d5"
    }
  }'
```
</RequestExample>

<ResponseExample>
```json title="Response"
{
  "data": {
    "customer_id": "9e3cccad-e9ae-47a0-81ee-063af0159310",
    "feature_id": "virtual_cards",
    "status": "active",
    "activated_at": "2026-01-09T10:29:16.000Z",
    "data": {
      "application_id": "a14ec356-f33d-4384-ba68-4d9bfa19765b"
    }
  },
  "error": null
}
```
</ResponseExample>

Save `data.data.application_id`. If activation returns `pending_liveness`, send the customer to `websdk_url`, complete the check, and retry with the same idempotency key.

</Step>

<Step title="Wait for application approval">

Retrieve the application until `application_status` becomes `approved`. Stop if it becomes `denied`, `locked`, or `canceled`.

<RequestExample>
```bash title="Request"
curl --request GET \
  --url https://api.gravv.xyz/v1/cards/applications/a14ec356-f33d-4384-ba68-4d9bfa19765b \
  --header 'Api-Key: <API_KEY>'
```
</RequestExample>

<ResponseExample>
```json title="Response"
{
  "data": {
    "id": "a14ec356-f33d-4384-ba68-4d9bfa19765b",
    "customer_id": "9e3cccad-e9ae-47a0-81ee-063af0159310",
    "application_status": "approved"
  },
  "error": null
}
```
</ResponseExample>

</Step>

<Step title="Issue the card">

Create the card after the application is approved.

<RequestExample>
```bash title="Request"
curl --request POST \
  --url https://api.gravv.xyz/v1/cards \
  --header 'Api-Key: <API_KEY>' \
  --header 'Idempotency-Key: card-issuance-<UUID>' \
  --header 'Content-Type: application/json' \
  --data '{
    "customer_id": "9e3cccad-e9ae-47a0-81ee-063af0159310",
    "card_type": "virtual",
    "card_limit": 500,
    "name_on_card": "Sarah Johnson"
  }'
```
</RequestExample>

<ResponseExample>
```json title="Response"
{
  "data": {
    "id": "dce0192a-9b3d-440b-9500-33dc9ac8dc20",
    "message": "Card creation request is processing",
    "status": true,
    "fee_charged": true,
    "fee_pending": false
  },
  "error": null
}
```
</ResponseExample>

Save `data.id` as the card ID. Retrieve the card until its status is ready for use.

</Step>

<Step title="Fund the card">

Transfer funds from a funded internal account to the issued card.

<RequestExample>
```bash title="Request"
curl --request POST \
  --url https://api.gravv.xyz/v1/transfer \
  --header 'Api-Key: <API_KEY>' \
  --header 'Idempotency-Key: card-funding-<UUID>' \
  --header 'Content-Type: application/json' \
  --data '{
    "source": {
      "source_type": "internal_account",
      "id": "b9c2cb0d-e09a-496f-8655-d8c4b7aaf2f8"
    },
    "destination": {
      "destination_type": "card",
      "id": "dce0192a-9b3d-440b-9500-33dc9ac8dc20"
    },
    "amount": 250,
    "description": "Initial card funding",
    "customer_id": "9e3cccad-e9ae-47a0-81ee-063af0159310",
    "client_reference": "card-fund-2026-001"
  }'
```
</RequestExample>

<ResponseExample>
```json title="Response"
{
  "data": {
    "amount": "250",
    "reference": "550e8400-e29b-41d4-a716-446655440000",
    "transfer_status": "pending",
    "transaction_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
  },
  "error": null
}
```
</ResponseExample>

Track the transfer until it completes before allowing the customer to spend the funds.

</Step>

<Step title="Withdraw funds from the card">

Move unused card funds back to the account configured during card activation.

<RequestExample>
```bash title="Request"
curl --request POST \
  --url https://api.gravv.xyz/v1/cards/withdraw \
  --header 'Api-Key: <API_KEY>' \
  --header 'Idempotency-Key: card-withdrawal-<UUID>' \
  --header 'Content-Type: application/json' \
  --data '{
    "card_id": "dce0192a-9b3d-440b-9500-33dc9ac8dc20",
    "amount": 100
  }'
```
</RequestExample>

<ResponseExample>
```json title="Response"
{
  "data": {
    "tx_hash": "0x2e5d0af9189b4b4c23bc64b96295e730609ec91e50e452a5da0a4af4bfe5c192"
  },
  "error": null
}
```
</ResponseExample>

</Step>
</Steps>

See [Cards](/platform/cards/overview), [card applications](/platform/cards/create-a-card-application), and the [Cards API Reference](/api-reference/cards/overview) for lifecycle and status details.

