> ## Documentation Index
> Fetch the complete documentation index at: https://www.bitnob.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Bitnob has two APIs. The Business API (payouts, cards, trading, virtual accounts, stablecoin and bitcoin transfers) is at https://api.bitnob.com. The Enterprise API (non-custodial wallets) is at https://api.platform.bitnob.com.
> Business API auth: sign every request with HMAC-SHA256 and send four headers: `X-Auth-Client` (your client ID), `X-Auth-Timestamp` (Unix seconds), `X-Auth-Nonce` (16 random bytes, hex), and `X-Auth-Signature`, the hex HMAC-SHA256 of `CLIENT_ID:TIMESTAMP:NONCE:BODY` keyed with your client secret. BODY is the exact request body string you send, or an empty string. A missing header, a bad signature, or a timestamp more than about 5 minutes off returns `401`.
> Enterprise API auth: send your key in the `X-API-Key` header. Write requests such as creating a transaction also need an `Idempotency-Key` header, or they fail with `idempotency_key_required` before anything happens.
> Sandbox and production share the Business API base URL. The credentials you sign with select the environment, and `GET /api/whoami` returns it in `data.environment`. Use sandbox credentials in sample code and tests, and never put live credentials in code.
> Amounts are strings unless stated otherwise. Never parse them into floats. Balances, transactions, withdrawals (`POST /api/withdrawals`) and virtual accounts use integer strings in the smallest unit: satoshis for BTC, 6 decimals for USDT and USDC, kobo for NGN.
> Payouts and trading use decimal strings in major units: a payout quote `amount` of `"1"` is 1 USDT, and a trading `quantity` of `"0.0001"` is 0.0001 BTC. Payout responses also carry `cent_amount`, the settlement amount in minor units.
> Card amounts are micro-units (1 USD = 1,000,000). Send them as JSON integers. Card responses return them as integer strings, and card webhooks as integers.
> Generate a unique `reference` for each money movement before the first attempt, and reuse it on retries. A reused reference returns `409` on payout quotes (`ALREADY_EXISTS`), withdrawals (`DUPLICATE_KEY_ERROR`) and card creation (`ALREADY_EXISTS`). It returns the existing record on NGN-pair trading orders and virtual accounts. It isn't checked on crypto-pair trading orders, so look the order up with `GET /api/trading/orders/{reference}` before resending.
> Quotes expire at `expires_at`; read it from the response instead of assuming a window. An expired trading quote returns `422` `PRECONDITION_FAILED`, and an expired payout quote returns `400` `VALIDATION_ERROR`. Create a new quote rather than retrying. A payout quote can be initialized once, and a trading quote is consumed by the order that fills it.
> Webhooks: verify the `x-bitnob-signature` header, the hex HMAC-SHA512 of the raw request body keyed with your webhook secret, before parsing JSON. Compare in constant time and de-duplicate on `event_id`. A successful API response means accepted: confirm the outcome from the webhook, such as `payouts.withdrawal.success`.
> Errors return `status`, `code` and `detail`. Branch on `code`, never on `detail`. Since the November 5, 2026 response format change, each company gets either the current or the new error codes until its cutoff date, so handle both: `PROVIDER_ERROR` or `PROCESSING_ERROR`, and `BVN_PROVIDER_UNAVAILABLE` or `BVN_VERIFICATION_UNAVAILABLE`. A body that fails to parse returns `{"error": {"code": "BAD_REQUEST"}}`.

# Set your card decline limit

> Choose how many declines a card can take before it is terminated, from the dashboard. The limit runs from 2 to 11 and defaults to 3.

Each time a payment on one of your cards is declined for one of the reasons below, it counts toward your decline limit. The first decline is free. Every decline after that costs \$0.75. When a card reaches the limit, the fee is charged and the card is terminated.

The limit is set for your whole business, and the default is 3. You can change it from the dashboard. There is no API endpoint for it.

## Declines that count

* **Insufficient funds**: the card doesn't have enough balance for the payment.
* **Inactive card**: a payment is attempted on a frozen card.
* **Reversed authorization**: a payment was approved but the merchant never completed it, so it was reversed.

A successful authorization on the card resets its count to zero.

## What each limit costs

The number of charged declines is always one less than the limit.

| Decline limit | Free declines | Charged declines | Most a card can be charged |
| - | - | - | - |
| 2 | 1 | 1 | \$0.75 |
| 3 (default) | 1 | 2 | \$1.50 |
| 5 | 1 | 4 | \$3.00 |
| 11 | 1 | 10 | \$7.50 |

At the default limit of 3:

| Decline | Charge | What happens |
| - | - | - |
| 1st | No charge | Card stays active |
| 2nd | \$0.75 | Card stays active |
| 3rd | \$0.75 | Card is terminated |

A higher limit gives a card more room before it is terminated, but more of its declines are charged.

## Set the limit

**1. Open the card decline limit**

Sign in to the [dashboard](https://app.bitnob.com/) and go to **Settings** > **Controls** > **Card decline limit**. **Maximum consecutive declines** shows your current limit.

**2. Enter a new limit**

Select **Edit**, then enter a whole number from 2 to 11 in **Maximum consecutive declines**. A limit of 1 isn't allowed.

![Editing the maximum consecutive declines in dashboard settings, with an allowed range of 2 to 11](https://mintcdn.com/bitnob/EWF3D5LyWUtRnhN9/images/card-decline-limit.png?fit=max\&auto=format\&n=EWF3D5LyWUtRnhN9\&q=85\&s=bacdd848ac865a88e69b927b2aee5c99)

**3. Save**

Select **Save**. The new limit applies to all your active cards and to any card you create afterward.

Only the Owner, Manager, and Treasury officer roles can change the limit. Everyone else can't change it.

The decline policy can't be turned off. The limit is the only setting.

## Who it applies to

The limit applies to every standard card on your business: both team cards and customer cards.

## Where the fees come from

Decline fees are taken from your business's central wallet. If the wallet doesn't have enough to cover a fee, the fee is still recorded and is settled the next time the wallet is funded. A short wallet doesn't terminate the card.

## Terminated cards

Termination is final. A terminated card can't be reactivated, and raising the limit doesn't bring it back. To keep transacting, create a new card. The standard \$1.00 creation fee applies.

## Track declines

Each decline fee sends a `virtualcard.transaction.declined.charge` webhook. Its `violationCount` field shows how many declines the card has reached, so you can warn the cardholder or fund the card before it hits the limit. See [Fees and decline rules](https://www.bitnob.dev/docs/card-issuing/card-fees.md#webhook-events).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.