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

# Billing and usage

> How verifications are paid for - in the free trial, on a plan, or from credits with no plan - which checks are charged per use, and what your integration sees when an organization can't pay.

An Urtentic organization starts on a free trial. After that it pays for verifications with a plan, or, with no plan, from its credits as it goes. This page explains how a verification is paid for and how to handle the responses your integration gets when an organization can't pay. Plans, the price of every check and a cost calculator are on the **Billing** page of the [dashboard](https://app.urtentic.com), under **Plans & pricing**. **Overview** shows the current plan, usage and credit balance, and **History** lists payments and credit activity.

## Free trial, plans, and paying as you go

| | Free trial | Plan | No plan (pay as you go) |
| - | - | - | - |
| Monthly fee | None | Yes, or yearly at 16% off | None |
| Included verifications | 50, for 14 days | Set by the plan | None |
| Beyond what's included | Paid from credits at pay-as-you-go prices | Paid from credits at plan prices | Every verification is paid from credits at pay-as-you-go prices |
| Phone, government and watchlist checks | Paid from credits per use | Paid from credits per use | Paid from credits per use |

New organizations start on the free trial. When it ends, an organization with no plan simply pays for each verification from its credits - there's nothing to switch to. The same applies when a plan stops: once it's cancelled, or once a failed renewal payment's grace period is over. Choosing a plan is a checkout on **Billing** > **Plans & pricing**, and the plan starts straight away.

Paying as you go has its own, higher price for each check a plan includes, so a plan becomes the cheaper choice as volume grows. Phone, government and watchlist checks cost the same either way.

## How a verification is paid for

**1. Included verifications first**

A plan includes a number of verifications per billing period, and the free trial includes 50. While those last, a new verification is covered.

**2. Credits after that**

Beyond them, and for every verification with no plan, a verification is paid from the organization's credits. It costs the sum of the prices of its workflow's plan-covered checks (document verification, liveness, video agreement, proof of residency, location intelligence, email check): the plan price on a plan, the pay-as-you-go price otherwise. The amount is reserved when the verification starts and charged when it finishes.

**3. Refused when credits can't pay**

If nothing includes the verification and the credits can't cover it, starting one fails with HTTP `402`. See [Handling HTTP 402](#handling-http-402).

A verification only counts towards the plan, or is charged to credits, when it finishes as `SUCCESS`, `REJECTED` or `NEEDS_REVIEW`. These cost nothing:

* Verifications that end `ABANDONED`.
* Verifications rejected only because of a failure on our side, where every serious step error is `internal-error` or `network-error`.

Charges are rounded up to the next cent. The current price of each check, on a plan and paying as you go, is on **Billing** > **Plans & pricing** > **Pay as you go** > **Pricing**.

A verification is charged at the prices in effect when it starts. Prices can change: plan fees with at least 30 days' notice, taking effect at the next renewal after it, and per-check prices with 14 days' notice, or sooner when a third-party data provider changes its charges. The full billing terms are in section 5 of the [Terms and Conditions](https://urtentic.com/privacy-policy?tab=terms).

## Checks charged per use

Phone verification, government database checks and watchlist screening pay a third party every time they run, so they are never covered by a plan. Each use is paid from credits - on a plan, in the free trial, and with no plan - so they need credits: a verification whose workflow uses them is refused while the organization has none.

| Check | When it's charged | If the credits can't pay |
| - | - | - |
| Phone check | Each confirmation SMS, when it's sent: the first code and every resend, with no limit. | No SMS is sent. The verification ends `NEEDS_REVIEW`. |
| Government check | Each lookup, once per verification. The price depends on the database (BVN, NIN, driver's licence or voter's card). | The lookup is skipped. The verification ends `NEEDS_REVIEW`. |
| Watchlist screening | Each screening, once per verification | The screening is skipped. The verification ends `NEEDS_REVIEW`. |

If the SMS provider, the government database or the screening provider fails, the charge is refunded automatically.

## Credits

Credits are a prepaid balance: one credit is one US dollar. The organization's owner or an admin buys them from **Billing** > **Overview**, between 10 and 10,000 USD at a time. The owner is emailed when the balance drops below 5 USD, or below the amount the organization sets on the Credits card.

> [!WARNING]
>
> Credits don't expire, but they can't be withdrawn or refunded.

## Handling HTTP 402

[Start verification](https://docs.urtentic.com/api-reference/introduction.md) returns `402 Payment Required` when the organization can't start a verification. The `code` tells you why:

| `code` | Meaning | What the organization needs to do |
| - | - | - |
| `QUOTA_EXCEEDED` | Nothing includes the verification - the plan's or trial's allowance is used up, or the organization has no plan - and its credits can't cover it | Buy credits or choose a (bigger) plan |
| `CREDITS_REQUIRED` | The workflow uses a check paid per use (phone, government or watchlist) and the organization has no credits | Buy credits, or remove the check from the workflow |

```json 402 response theme={null}
{
  "code": "QUOTA_EXCEEDED",
  "message": "Your plan's quota of 500 verifications has been reached and your credit balance can't cover another one. Upgrade your plan or buy credits to continue.",
  "tier": "STARTER",
  "included": 500,
  "used": 500,
  "upgradeUrl": "/billing/checkout"
}
```

`used` is only set for `QUOTA_EXCEEDED`. During the 7-day grace period after a failed renewal payment, the plan keeps working; after it, the organization has no plan and pays from its credits.

```javascript JavaScript theme={null}
const response = await fetch("https://api.urtentic.com/api/v1/verifications", {
  method: "POST",
  headers: {
    "X-CLIENT-ID": process.env.URTENTIC_CLIENT_ID,
    Authorization: `Bearer ${process.env.URTENTIC_SECRET_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ flowId: "40f85c69-b27a-46e8-9115-691401acb5df" }),
});

if (response.status === 402) {
  const { code, message } = await response.json();
  // Don't retry: ask the organization's owner to buy credits or change plan.
  throw new Error(`Urtentic billing blocked this verification (${code}): ${message}`);
}
if (!response.ok) {
  throw new Error(`Starting the verification failed with HTTP ${response.status}`);
}
const { verificationId } = await response.json();
```

```python Python theme={null}
import os
import requests

response = requests.post(
    "https://api.urtentic.com/api/v1/verifications",
    headers={
        "X-CLIENT-ID": os.environ["URTENTIC_CLIENT_ID"],
        "Authorization": f"Bearer {os.environ['URTENTIC_SECRET_KEY']}",
    },
    json={"flowId": "40f85c69-b27a-46e8-9115-691401acb5df"},
    timeout=30,
)

if response.status_code == 402:
    body = response.json()
    # Don't retry: ask the organization's owner to buy credits or change plan.
    raise RuntimeError(f"Urtentic billing blocked this verification ({body['code']}): {body['message']}")
response.raise_for_status()
verification_id = response.json()["verificationId"]
```

## Phone codes when credits run out

If you build your own phone-check screen instead of using the [direct link](https://docs.urtentic.com/sdk/direct-link/getting-started.md), request the code with the verification it belongs to:

```bash theme={null}
curl -X POST https://api.urtentic.com/api/v1/workflows/{workflowId}/otp \
  -H "X-CLIENT-ID: ${CLIENT_ID}" \
  -H "Authorization: Bearer ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"key": "+2348012345678", "channel": "PHONE", "verificationId": "85c94e71-6e3f-4a19-b15c-781d8a876542"}'
```

The response says whether a code was actually sent:

```json theme={null}
{ "sent": false }
```

`sent: false` means the organization's credits couldn't pay for the SMS, so nothing was sent. Don't ask the person for a code. Submit the phone number without an OTP and let the verification continue. It ends `NEEDS_REVIEW`.

| Status | `code` | Meaning |
| - | - | - |
| `400` | `VERIFICATION_ID_REQUIRED` | `verificationId` is missing |
| `400` | `VERIFICATION_NOT_IN_PROGRESS` | The verification has already finished |
| `404` | `VERIFICATION_NOT_FOUND` | No verification with that ID in this organization and workflow |

## Spotting a skipped check in results

A check skipped because the credits couldn't pay appears on the verification as a step error with `errorType` `insufficient-balance` and `severity` `MEDIUM`:

* On the `phone-owner-validation` step for a phone check.
* On the `government-check` step for a government check, and on the `watchlist` step for a watchlist screening. These steps have `status` `402` and no `data`.

```json theme={null}
{
  "stepId": "government-check",
  "status": 402,
  "error": {
    "severity": "MEDIUM",
    "errorType": "insufficient-balance",
    "message": "The government check was skipped because the credit balance couldn't cover it"
  }
}
```

Use this to tell a balance problem apart from a genuine verification failure, for example to alert your own team instead of rejecting the customer.

## Next steps

> **[Webhooks](https://docs.urtentic.com/webhooks/overview.md)**
>
> Get notified when a verification finishes.

> **[API reference](https://docs.urtentic.com/api-reference/introduction.md)**
>
> Endpoints, parameters and responses.


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