---
title: "Issue a business card"
description: "In sandbox, issue a card printed with a business customer's name to one of its associated persons."
---
Use this recipe in sandbox to issue a card printed with a business customer's name to one of the business's associated persons.

**Who it is for.** This recipe is for an expense platform whose client company wants its name printed on staff cards.

**Status.** Available in sandbox only. Not yet available in live. Contact support before you offer business cards.

## Money example

The card shows the business name "Northwind Logistics".

1. Jane, the finance lead, gets a card.
2. You move 1,000 USD from the company account to the card.
3. Jane pays a 240 USD software invoice. The card now holds 760 USD.

## Before you start

KYB is KYC for a business, which checks the company and its people. See the [Glossary](/getting-started/glossary).

| Prerequisite | How to check |
| :-- | :-- |
| A `business` customer with a `business_name` | `GET /v1/customers/{customer_id}` on the business shows `type` `business` |
| The business finished KYB | The business's `basic` KYC is `completed` |
| The cardholder is one of the business's associated persons and is verified | The person is in `associated_persons[].id`, and that person's `basic` KYC is `completed` |
| Your card account | See [the hosted-check recipe](/recipes/cards/issue-a-virtual-card-after-a-hosted-check#before-you-start) |
| The person has no card application yet | `GET /v1/cards?customer_id=…` returns nothing |

## Find out what is required

`GET /v1/customers/{customer_id}` on the business returns the business name, its KYB status and its associated persons. If one of them is missing, the application call names it.

## Steps

### 1. Open the business card application

<CodeGroup>
```bash title="cURL"
curl --request POST \
     --url https://api.gravv.xyz/v1/cards/applications/new \
     --header 'Api-Key: <API_KEY>' \
     --header 'Idempotency-Key: 19781350-fe75-4ff1-a062-47c62eb6352f' \
     --header 'Content-Type: application/json' \
     --data '
{
  "type": "business",
  "customer_id": "9e8d7c6b-5a49-4382-a1b0-c9d8e7f6a5b4",
  "business_customer_id": "0d6c2f4e-6a1b-4f0e-9b8f-5c2a7d3e1f00",
  "account_id": "9b40be8d-9d74-4d2a-8897-dea3ef80ad23",
  "annual_remuneration": 60000,
  "estimated_monthly_limit": 3000,
  "ip_address": "203.0.113.24"
}
'
```
```javascript title="Node"
const response = await fetch("https://api.gravv.xyz/v1/cards/applications/new", {
  method: "POST",
  headers: {
    "Api-Key": process.env.GRAVV_API_KEY,
    "Idempotency-Key": "19781350-fe75-4ff1-a062-47c62eb6352f",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "type": "business",
    "customer_id": "9e8d7c6b-5a49-4382-a1b0-c9d8e7f6a5b4",
    "business_customer_id": "0d6c2f4e-6a1b-4f0e-9b8f-5c2a7d3e1f00",
    "account_id": "9b40be8d-9d74-4d2a-8897-dea3ef80ad23",
    "annual_remuneration": 60000,
    "estimated_monthly_limit": 3000,
    "ip_address": "203.0.113.24"
  }),
});
console.log(response.status, await response.json());
```
```python title="Python"
import os

import requests

response = requests.post(
    "https://api.gravv.xyz/v1/cards/applications/new",
    headers={
        "Api-Key": os.environ["GRAVV_API_KEY"],
        "Idempotency-Key": "19781350-fe75-4ff1-a062-47c62eb6352f",
        "Content-Type": "application/json",
    },
    json={
        "type": "business",
        "customer_id": "9e8d7c6b-5a49-4382-a1b0-c9d8e7f6a5b4",
        "business_customer_id": "0d6c2f4e-6a1b-4f0e-9b8f-5c2a7d3e1f00",
        "account_id": "9b40be8d-9d74-4d2a-8897-dea3ef80ad23",
        "annual_remuneration": 60000,
        "estimated_monthly_limit": 3000,
        "ip_address": "203.0.113.24",
    },
)
print(response.status_code, response.json())
```
</CodeGroup>

```json title="Response"
{
  "data": {
    "message": "Card application request successful",
    "status": true,
    "id": "b25fd467-a44e-4495-8b79-5e0cab2a876c"
  },
  "error": null
}
```

Set `customer_id` to the person and `business_customer_id` to the business. `estimated_monthly_limit` must not be above `annual_remuneration`. `ip_address` is the cardholder's IP address.

### 2. Check approval

List the applications with `GET /v1/cards/applications`. The item with this `id` shows `application_status` `approved`. Sandbox approves applications at once.

### 3. Issue the card

<CodeGroup>
```bash title="cURL"
curl --request POST \
     --url https://api.gravv.xyz/v1/cards \
     --header 'Api-Key: <API_KEY>' \
     --header 'Idempotency-Key: 368f9b5b-3958-4de3-87c7-ea03e27a5165' \
     --header 'Content-Type: application/json' \
     --data '
{
  "customer_id": "9e8d7c6b-5a49-4382-a1b0-c9d8e7f6a5b4",
  "card_type": "virtual",
  "card_limit": 500,
  "name_on_card": "Jane Doe"
}
'
```
```javascript title="Node"
const response = await fetch("https://api.gravv.xyz/v1/cards", {
  method: "POST",
  headers: {
    "Api-Key": process.env.GRAVV_API_KEY,
    "Idempotency-Key": "368f9b5b-3958-4de3-87c7-ea03e27a5165",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "customer_id": "9e8d7c6b-5a49-4382-a1b0-c9d8e7f6a5b4",
    "card_type": "virtual",
    "card_limit": 500,
    "name_on_card": "Jane Doe"
  }),
});
console.log(response.status, await response.json());
```
```python title="Python"
import os

import requests

response = requests.post(
    "https://api.gravv.xyz/v1/cards",
    headers={
        "Api-Key": os.environ["GRAVV_API_KEY"],
        "Idempotency-Key": "368f9b5b-3958-4de3-87c7-ea03e27a5165",
        "Content-Type": "application/json",
    },
    json={
        "customer_id": "9e8d7c6b-5a49-4382-a1b0-c9d8e7f6a5b4",
        "card_type": "virtual",
        "card_limit": 500,
        "name_on_card": "Jane Doe",
    },
)
print(response.status_code, response.json())
```
</CodeGroup>

The first card's `id` is the application id. Next, [top up the card](/recipes/cards/top-up-a-card).

## What can go wrong

| Response (HTTP 400) | Why | Fix |
| :-- | :-- | :-- |
| `a business customer cannot hold a card; apply with type "business" for one of its associated persons` | `customer_id` is the business | Send the person as `customer_id` and the business as `business_customer_id` |
| `an associated person's card must be a business card; apply with type "business" and their business_customer_id` | The request has no `type` | Add `"type": "business"` |
| `business_customer_id is required when type is "business"` | `business_customer_id` is missing | Send it |
| `the business must complete KYB before cards can be issued under it` | The business is not verified | Finish KYB |
| `the business has no business_name to print on its cards` | The business has no `business_name` | Update the business |
| `customer_id is not an associated person of this business` | The person is not linked to the business | Add the person to the business |
| `basic level kyc needs to be completed to create an application` | The person is not verified. The API checks this first | Verify the person |
| `estimated_monthly_limit must be lesser than annual_renumeration` | `estimated_monthly_limit` is above `annual_remuneration` | Lower `estimated_monthly_limit` |
| 200 with an application that has no `message` | The person already has a card application, and the API returns it unchanged | Use a person with no application yet |

## Webhooks you will receive

Gravv sends no webhook when the application opens in sandbox. For funding and card events, see [Top up a card](/recipes/cards/top-up-a-card#webhooks-you-will-receive).

## Testing in sandbox

This recipe runs in sandbox. **Sandbox KYC does not complete today**, so you need an associated person verified earlier and with no card application.

## Reference

- [Create card application](/api-reference/cards/post-v1-cards-applications-new)
- [Create a card application](/platform/cards/create-a-card-application)
