Reference
Endpoints
| Method | Path | Auth | Cost |
|---|---|---|---|
| POST | /v1/search | Bearer | billed per unit |
| POST | /v1/count | Bearer | free |
| GET | /v1/sources | Bearer | free |
| GET | /v1/balance | Bearer | free |
| GET | /v1/orders | Bearer | free, paginated |
| GET | /v1/orders/{order_id} | Bearer | free |
| GET | /v1/files/{order_id}.csv | none | free until TTL |
| GET | /v1/ledger | Bearer | free, paginated |
| POST | /v1/funding/invoices | Bearer | free |
| GET | /v1/funding/invoices | Bearer | free, paginated |
| GET | /v1/funding/invoices/{invoice_id} | Bearer | free |
Token issuance and revocation are handled by the service administrator; there are no token-management endpoints.
Conventions
- Auth:
Authorization: Bearer sk_live_.... Missing, invalid, or revoked tokens get401 unauthorized. - Content type:
application/jsonon all requests. Responses are JSON except CSV files. - Money: integer cents, always.
- Time: ISO 8601 UTC, e.g.
2026-09-17T12:00:00Z. - Strict schemas: unknown request fields are rejected (
422 unknown_field). - Request ids: every response carries an
X-Request-Idheader; errors also embed it asrequest_id. Quote it in support requests.
Pagination
List endpoints (orders, ledger, funding/invoices) paginate newest-first: ?limit=50&cursor=... with limit 1–200.
{"items": [...], "next_cursor": null}
next_cursor is opaque; pass it back as-is until it is null.
Orders
GET /v1/orders/{order_id} returns:
{
"order_id": "ord_9f8e7d6a...",
"root_order_id": "ord_9f8e7d6a...",
"parent_order_id": null,
"type": "search",
"created_at": "2026-09-17T12:00:00Z",
"expires_at": "2026-09-20T12:00:00Z",
"query": {"domain": "example.org"},
"matched_rows": 2234,
"delivered_rows": 1000,
"remaining_rows": 1234,
"cost_cents": 15130,
"file_url": "/v1/files/ord_9f8e7d6a....csv",
"by_source": {"a": 448, "b": 45, "c": 507}
}
Counts are units. by_source describes this chunk (unlike /v1/count's full-match version). remaining_rows is 0 exactly when further continuations return 410. Unknown ids — including other customers' — return 404 order_not_found. Orders persist forever as accounting records, even after their files expire.
Files
GET /v1/files/{order_id}.csv — no auth; the URL is the credential. Returns 200 with Content-Type: text/csv; charset=utf-8 until expires_at, then 410 file_expired.
CSV format:
- Header
domain,url,login,pass,source, always present even for empty results. - One line per URL; a unit's URLs are never split across chunks.
sourceis the unit's billing-attributed (cheapest) source.- RFC 4180 quoting, UTF-8, LF line endings, no BOM.
- Lines are in delivery order, so concatenated chunks form the complete, deterministically ordered match.
Warning — spreadsheet formula injection. Cells may begin with
=,+,-, or@and can execute as formulas when the file is opened in Excel or similar. Import as plain text/data, or sanitize cells before opening.
Errors
Errors are RFC 9457 application/problem+json with a closed code vocabulary:
{
"type": "https://api.basegrep.com/errors/cost-exceeds-max-cost",
"title": "Cost exceeds max_cost_cents",
"status": 402,
"code": "cost_exceeds_max_cost",
"detail": "Chunk costs 15130 cents; effective limit is 4000 (stated max_cost_cents).",
"instance": "/v1/search",
"request_id": "req_01j8x9...",
"actual_cost_cents": 15130,
"max_cost_cents": 4000,
"balance_cents": 12300,
"limit_source": "max_cost_cents"
}
| Status | Code | When |
|---|---|---|
| 400 | invalid_json | Unparseable body |
| 401 | unauthorized | Missing, invalid, or revoked token |
| 402 | cost_exceeds_max_cost | Chunk cost exceeds the effective limit; always atomic |
| 404 | order_not_found, invoice_not_found | Unknown or cross-token id |
| 409 | idempotency_in_progress | Same idempotency key still executing |
| 410 | file_expired, order_expired, order_exhausted | Terminal states |
| 422 | validation_error | Malformed request; see subcodes |
| 422 | idempotency_key_conflict | Key reused with a different body |
| 429 | rate_limited | With Retry-After (seconds) |
validation_error subcodes: missing_domain, invalid_domain, unknown_source, source_in_both_lists, max_rows_invalid, max_cost_cents_invalid, unknown_field, query_with_continue.
Rate limits
Per token: /v1/count 60/min, /v1/search 60/min, everything else 300/min. On 429, wait for Retry-After and retry — search retries are free if you reuse the idempotency key.