# Billing and what a call costs

A call that succeeds is charged once, at the price printed on its page, from $0.0003; an empty result is charged only where the endpoint says so. A failed call is never charged, and the same Idempotency-Key within 24 hours is never charged twice.

## What a call costs

- **Per call**: one price for the page, however many items it holds. 196 of the 207 endpoints are priced this way; `tiktok.videos.search` is $0.0020 a call.
- **Per item**: a price for each item returned, with a minimum for a call and a most one call can cost. 11 endpoints are priced this way; [X community posts](https://dataxapi.com/apis/x/communities/posts/list/) is $0.0003 an item, at least $0.0003 and at most $0.0060 a call.

The price is in three places: on the endpoint's page, in `GET /v1/catalog` (each endpoint's `pricing`), and in [prices.json](https://dataxapi.com/prices.json). The [pricing page](https://dataxapi.com/pricing/) lists them all. Prices are in US dollars only.

Every answer says what it cost, in `meta.billing`:

- `amount`: What this call was charged.
- `currency`: Always `USD`.
- `balance_after`: The balance after it.

To cap a call, send `X-Max-Price`: a call that could cost more is refused before it runs (400 [`max_price_exceeded`](https://dataxapi.com/docs/errors/#max_price_exceeded)).

## When a call is charged

| Outcome | What comes back | Charged? |
| --- | --- | --- |
| Complete | The data, `result_status: complete`. | Yes, once. |
| A batch where some inputs were not found | What was found in `data.items`, the rest in `data.missing` with a reason; `partial`. | Per item: only the items returned. Per call: once. |
| A list with broken items | The broken ones are dropped and counted in `warnings`. | Per item: only the valid ones. Per call: once, if at least one is valid. |
| Nothing matches a valid request | An empty `items`; `empty`. Do not retry with the same parameters. | Only where the endpoint says so (`pricing.charge_when_empty`, on its page): 128 of 207 endpoints charge it. |
| A batch where nothing was found | `empty`, every input in `data.missing`. | No. |
| The object does not exist | 404 [`not_found`](https://dataxapi.com/docs/errors/#not_found). | No. |
| An error or a timeout, ours or the source's | A 5xx that says whether to retry. | No. Retry under the same `Idempotency-Key`. |
| [`settlement_unknown`](https://dataxapi.com/docs/errors/#settlement_unknown) | Rare: the result was saved, and the confirmation did not come back. | Not known. Do not take it as not charged: ask again under the same key, or look the call up by its request ID. |

## Idempotency

1. The same `Idempotency-Key` with the same request, within 24 hours, returns the first result. Nothing runs again and nothing is charged again.
2. The same key with a different request is 409 [`idempotency_conflict`](https://dataxapi.com/docs/errors/#idempotency_conflict).
3. A failure that may be retried is not kept: the same key then runs the call anew. A failure that may not (the object does not exist, a parameter is wrong) answers the same error for 24 hours.
4. The SDKs and the command line send a key by themselves on every call. Over plain HTTP you send it.

```bash
curl -G "https://api.dataxapi.com/v1/tiktok/videos/search" \
  --data-urlencode "query=space station" \
  -H "Authorization: Bearer $DATAXAPI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "X-Max-Price: 0.002"
```

Two free lookups tell what became of a call:

- `GET /v1/calls?idempotency_key=…`: What a key stands for now (`state`): `free`, `in_progress`, `settled`, `failed`, `retryable` or `retry_refused`. Asking starts nothing.
- `GET /v1/calls/{request_id}`: One call's record: `status` (`in_progress`, `settled`, `released`) and `charged`.

## Balance and top-ups

- The balance is prepaid. There is no subscription. Top up from $10 on the [Billing page](https://dataxapi.com/console/billing/) of the Console.
- The balance never expires.
- Top-ups are final. Try the service on the free credit ($0.10, once per email) before you top up.
- A call the balance does not cover is refused before it runs: 402 [`insufficient_balance`](https://dataxapi.com/docs/errors/#insufficient_balance), with `required` and `available`. A call over a key's own limit is 402 [`key_budget_exceeded`](https://dataxapi.com/docs/errors/#key_budget_exceeded).

## Usage

`GET /v1/usage` sums the account's finished calls. It is free. `group_by` takes one or more of `day`, `capability`, `key_id`, `entry`, `source` and `end_user`; `since` and `until` set the period (the last 30 days when left out, 92 days at most); `format=csv` returns a file. Each row has `calls`, `settled` and `charged`.

```bash
curl -G "https://api.dataxapi.com/v1/usage" \
  --data-urlencode "group_by=day,capability" \
  -H "Authorization: Bearer $DATAXAPI_API_KEY"
```

---

Catalog revision c48ce454ae6c4c65. [HTML version](https://dataxapi.com/docs/billing/)
