# API conventions

These are selected design rules, not a working endpoint or a verified implementation. No account, key or package installation is required to read this reference.

## Fields and authentication

TrueFetch JSON fields use camelCase, including `productId`, `sourceId`, `thumbnailUrl` and `maxCostUsd`. Standard headers, protocol-defined fields, error-code values and URL slugs retain their prescribed names.

The selected authentication header is `Authorization: Bearer <key>`. The design also accepts `x-api-key` as an alias. Supplying both with different values produces `400 invalid_input`; the service must not silently choose one. Examples use an environment variable named `TRUEFETCH_API_KEY`, never a real key.

Keys are designed to be displayed in full only at creation and stored server-side as hashes. The selected scopes are `full` and `read_results`. A key may have a monthly USD spending cap. These controls must be verified before keys are issued; this preview issues none.

## Accepted work and polling

A task can finish within the synchronous waiting window or return an accepted handle while work continues. Poll the existing task handle instead of submitting the task again. A successful HTTP response when checking a task says the lookup succeeded; the task's own `status` determines whether collection succeeded, failed or remains in progress.

No synchronous waiting duration or polling throughput is promised by this preview. See [response outcomes](/docs/responses/) for terminal-state meanings.

## Pagination is not another collection

`page.nextCursor` reads the next portion of an existing snapshot. Treat it as opaque, keep its original value, and use it under the same authorized account. The cursor must be bound to the tenant, task, contract version and snapshot, with expiry enforced.

`page.hasMoreAtSource` and `page.continueToken` describe additional work at the source. Continuing collection creates a new acceptance and budget decision. It must not be hidden behind a supposedly free result read.

Reading a saved result or switching its data view does not create another business charge. A new collection can be billable even if the result resembles an earlier one. RapidAPI's request accounting is separate.

## Safe retries

Use `Idempotency-Key` for retrying the same submission. Its scope is tenant plus operation, including the same operation reached through different routes. Replay checks current authentication and permissions before looking up the original task, and resolves that task before attempting another reservation.

Do not reuse a key for different input. Do not replace a key merely because a connection timed out: first establish whether the original request was accepted. An expired key is an explicit error, not permission to silently run again. See [errors and recovery](/docs/errors/).

## Limits

Session, API-key and MCP execution share tenant limits. Reading results, checking task state and cancellation have separate control-request limits; exhausting execution allowance must not make accepted work inaccessible.

`429 rate_limited` includes a `Retry-After` hint and a scope such as `key`, `tenant`, `source` or `unbilledBudget`. Rate headers are node-local hints, not throughput guarantees. Source capacity, queue pressure and other controls may refuse work earlier. Exact released limits must be published with the operation.

## Versions and missing values

The design uses a major version in the API path and a dated `contractVersion` per operation. Removing or renaming fields, changing meanings or units, tightening accepted input and changing the billing unit are breaking changes. The planned ordinary deprecation window is at least 90 days, with notice and `Deprecation` and `Sunset` headers; this is not a claim that a version is live.

If a source stops providing an optional, nullable field, return `null` with a warning. If it stops providing a required field or essential meaning, suspend that capability until repaired or versioned. A warning must not disguise a broken delivery contract.

## Result lifetime

The selected defaults are seven days for results and 30 days for request logs; customers may shorten result retention. A stable `resultUrl` still checks ownership and expiry. It is not permanent storage. Downloaded copies are outside that URL's expiry mechanism. See [data practices](/data-practices/).
