# Batch reads

> Up to 100 profiles or tweets in one request.

Two endpoints take a list instead of one handle or id. They cost the same per object as the single endpoints,
answer in one round trip, and never charge for an input that returned nothing.

| Endpoint                | Input     | Max | Credits             |
| ----------------------- | --------- | --- | ------------------- |
| `POST /v1/users/batch`  | `handles` | 100 | 1 per profile found |
| `POST /v1/tweets/batch` | `ids`     | 100 | 1 per tweet found   |

Both also accept `GET` with a comma list: `/v1/users/batch?handles=x,github,vercel`.

## Request [#request]

```bash
curl -X POST https://api.xdataapi.io/v1/users/batch \
  -H "x-api-key: $KEY" -H "content-type: application/json" \
  -d '{"handles": ["x", "github", "nobody_here_12345"]}'
```

```json
{
  "data": [
    { "id": "783214", "handle": "X", "followers": 60738793, "...": "..." },
    { "id": "13334762", "handle": "github", "followers": 2900000, "...": "..." }
  ],
  "errors": [
    { "input": "nobody_here_12345", "code": "not_found", "message": "no user" }
  ],
  "items": 2,
  "credits_charged": 2,
  "balance_remaining": 4998,
  "cache": "miss",
  "cache_hits": 0,
  "request_id": "3d4f3d1c-..."
}
```

## Rules [#rules]

* `data` holds the objects that were found, in input order. Every input that returned nothing is in `errors`
  with a `code`: `not_found`, `access_denied`, `upstream_error`, or `no_credits`.
* Duplicates are folded. `@x` and `X` are the same handle.
* The cache is shared with the single endpoints. An object read in the last 10 minutes (profiles) or 5 minutes
  (tweets) is served from cache at half price; `cache_hits` says how many, and `cache` is `mixed` when a batch
  has both.
* When the balance covers only part of the list, the API fetches what it can pay for and returns the rest as
  `no_credits`. Send those again after a top-up.
* When nothing is found and every failure is transient, the answer is `503` with `retry-after`, and nothing is
  charged.
* `fresh=true` bypasses the cache for the whole list, at 2x.

Batch by numeric user id is not available yet. Resolve ids through `/v1/users/{id}/tweets?count=20` or ask
[hello@xdataapi.io](mailto:hello@xdataapi.io) if you need it.
