Create a card application

A card needs an approved application, and activating virtual_cards creates it. Follow the application in sandbox and in live.

You cannot create a card on its own. Every card needs an approved card application behind it, where Gravv's card program runs its own checks on the cardholder. You create the application by activating the card feature for the customer.

A money example. You activate cards for Ada with a daily limit of 300 USD in mind. In sandbox, the card program approves her application at once, and a virtual card with a 300 USD daily limit appears about 4 seconds later. In live, the card program reviews her application first. Once it is approved, you issue the card and fund it with 150 USD.

Before you start

  • Your card account is active. Its id is the account_id below.
  • The customer's basic KYC is completed, with a liveness check. See Card KYC and activation.
  • If you use a scoped API key, it needs feature:read and feature:activate.

Activate the card feature

Call Activate feature with feature_id virtual_cards:

curl --request POST \
     --url https://api.gravv.xyz/v1/risk/features/activate \
     --header 'Api-Key: <API_KEY>' \
     --header 'Idempotency-Key: f0444862-29aa-44bc-821a-29e0e137497c' \
     --header 'Content-Type: application/json' \
     --data '
{
  "customer_id": "5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42",
  "feature_id": "virtual_cards",
  "provider_data": {
    "annual_remuneration": 24000,
    "estimated_monthly_limit": 300,
    "account_id": "9b40be8d-9d74-4d2a-8897-dea3ef80ad23"
  }
}
'
Field Rule
annual_remuneration Yearly income in USD, a JSON number of at least 1000
estimated_monthly_limit A JSON number of at least 1. When a card is issued during activation (sandbox), it becomes that card's daily limit
account_id Always your card account's id, for every cardholder

Gravv fills in ip_address from the address your request comes from.

{
  "data": {
    "activated_at": "2026-10-13T11:20:05Z",
    "customer_id": "5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42",
    "feature_id": "virtual_cards",
    "status": "active"
  },
  "error": null
}

status active means Gravv submitted the application. It does not mean a card exists, and the response carries no application id. If the customer has no liveness check yet, the response has status pending_liveness and a websdk_url. See Activate feature.

Find the application

curl --request GET \
     --url 'https://api.gravv.xyz/v1/cards?customer_id=5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42' \
     --header 'Api-Key: <API_KEY>'
  • Sandbox. The card program approves the application at once, and Gravv issues a virtual card during activation. The list shows it with status active. Do not call Create a card unless you want a second card.
  • Live. The list shows an application row with status "" (no card yet). Its id is the application id, and it will also be the first card's id.

Live: follow the approval

Only List card applications shows application_status. The list has no customer filter, so page through it and match customer_id. Get card application returns the card status. That status stays "" until a card exists, so never poll it for approval.

curl --request GET \
     --url 'https://api.gravv.xyz/v1/cards/applications?items_per_page=100' \
     --header 'Api-Key: <API_KEY>'
application_status What to do
pending, manual_review Wait for cards.application.update
needs_verification, needs_information Show the cardholder the application_link, then wait for cards.application.update
approved Create the card
denied, locked, canceled Stop and contact support

In sandbox, application_link is always "".

What can go wrong

Response Why Fix
400 cards service: internal server error account_id left out, a number sent as a string, or the card program refused Send account_id, and send numbers as numbers. If the error persists, contact support with the customer id
400 failed to check liveness requirement: customer KYC must be completed before activating cards feature KYC not finished Wait for customer.kyc.status.completed
200 with message Feature activation already exists with status: active Already activated Find the card with GET /v1/cards?customer_id=…
400 card application is not yet approved! on POST /v1/cards Live application still under review Wait for approved, then send a new Idempotency-Key

Gravv stores every failed request against its Idempotency-Key for 24 hours. After you fix a request, send it with a new key.

The application route

Create card application (POST /v1/cards/applications/new) works today only for business cards in sandbox. Live does not support it. Use activation for every individual cardholder.

Was this page helpful?