xdataapi.io

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.

EndpointInputMaxCredits
POST /v1/users/batchhandles1001 per profile found
POST /v1/tweets/batchids1001 per tweet found

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

Request

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"]}'
{
  "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

  • 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 if you need it.

On this page