Issue a second or physical card

Give a cardholder up to 10 cards, sharing their balance or with a balance of their own. Physical cards are Not yet available.

Use this recipe to give a cardholder up to 10 cards. Each extra card shares the cardholder's balance or has a balance of its own. Physical cards are Not yet available.

Who it is for. This recipe is for a consumer app that gives Ada a separate card for subscriptions.

Status. Additional virtual cards are Available. Physical cards are Not yet available.

Money example

Ada's main card holds 131.25 USD.

  1. You issue her a "subscriptions" virtual card with a balance of its own and a 50 USD daily limit.
  2. You move 30 USD to the new card. The main card still holds 131.25 USD, and the subscriptions card holds 30 USD.
  3. A 9.99 USD subscription charges the subscriptions card, which leaves 20.01 USD on it.

Before you start

  • Ada's application is approved and her first card exists. Check with GET /v1/cards?customer_id=….
  • She holds fewer than 10 cards that are not blocked.

Find out what is required

Count Ada's cards:

curl --request GET \
 --url 'https://api.gravv.xyz/v1/cards?customer_id=5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42&status=active,freeze,inactive' \
 --header 'Api-Key: <API_KEY>'
const response = await fetch("https://api.gravv.xyz/v1/cards?customer_id=5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42&status=active,freeze,inactive", {
method: "GET",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
},
});
console.log(response.status, await response.json());
import os

import requests

response = requests.get(
"https://api.gravv.xyz/v1/cards?customer_id=5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42&status=active,freeze,inactive",
headers={
    "Api-Key": os.environ["GRAVV_API_KEY"],
},
)
print(response.status_code, response.json())

Steps

1. Issue a second virtual card with its own balance

Send a new Idempotency-Key for each extra card.

curl --request POST \
 --url https://api.gravv.xyz/v1/cards \
 --header 'Api-Key: <API_KEY>' \
 --header 'Idempotency-Key: 3211a0fd-795d-4218-bc6e-4966abe161ab' \
 --header 'Content-Type: application/json' \
 --data '
{
"customer_id": "5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42",
"card_type": "virtual",
"card_limit": 50,
"name_on_card": "Ada Obi",
"funding": {
"mode": "own"
}
}
'
const response = await fetch("https://api.gravv.xyz/v1/cards", {
method: "POST",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Idempotency-Key": "3211a0fd-795d-4218-bc6e-4966abe161ab",
"Content-Type": "application/json",
},
body: JSON.stringify({
"customer_id": "5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42",
"card_type": "virtual",
"card_limit": 50,
"name_on_card": "Ada Obi",
"funding": {
  "mode": "own"
}
}),
});
console.log(response.status, await response.json());
import os

import requests

response = requests.post(
"https://api.gravv.xyz/v1/cards",
headers={
    "Api-Key": os.environ["GRAVV_API_KEY"],
    "Idempotency-Key": "3211a0fd-795d-4218-bc6e-4966abe161ab",
    "Content-Type": "application/json",
},
json={
    "customer_id": "5b0f6c1e-2a8f-4c39-9d0e-0c7e3b9a1f42",
    "card_type": "virtual",
    "card_limit": 50,
    "name_on_card": "Ada Obi",
    "funding": {
        "mode": "own",
    },
},
)
print(response.status_code, response.json())
{
  "data": {
    "message": "Card creation request is processing",
    "status": true,
    "id": "0c9b8a7f-6e5d-4c4b-9a3f-2e1d0c9b8a76",
    "fee_charged": false
  },
  "error": null
}

Send {"mode": "shared"}, or leave funding out, to spend from the same balance as the main card.

2. Check it

GET /v1/cards/0c9b8a7f-6e5d-4c4b-9a3f-2e1d0c9b8a76 shows card_type virtual, status active and the 50 USD limit. Next, top it up.

Physical cards

Not yet available. A physical card cannot make a payment today. In sandbox, the request returns card creation failed! and leaves an empty card row. In live, the card starts inactive, and no API call activates it. For the shipping address rules, see Physical card shipping.

What can go wrong

Response (HTTP 400 unless noted) Why Fix
customer already holds the maximum of 10 cards The cardholder has reached the cap of 10 cards Block an unused card
missing idempotency key in request headers The request has no Idempotency-Key Add one
422 idempotency_key_reused You sent the same key with another body Use a new key for each card
funding.mode must be "shared" or "own" The mode is invalid Send shared or own
this card's balance is a new provider account whose application is <status>; retry with the same Idempotency-Key once it is approved In live, an own balance waits for approval See Issue expense cards to employees
card creation failed! The card program refused the card. Every physical card request in sandbox returns this today Issue a virtual card, and ignore the empty row

Webhooks you will receive

Gravv sends no webhook when you issue a card. You receive cards.transaction.* events once the cardholder uses the card.

Testing in sandbox

Additional virtual cards work in sandbox. A card with funding.mode own gets its own card_group_id. Physical cards fail to issue.

Reference

Was this page helpful?