Search lifecycle
Understand search IDs, job states, and how to retrieve results safely.
Keep the search ID
POST /search returns a job_id. Store it in your application and use it for subsequent GET requests. A job_id identifies the whole search; a source ID identifies a paper within the search's sources map.
Read the job state
| State | What to do |
|---|---|
queued | Wait, then poll again. |
running | Wait; work is still in progress. |
partial | Some track results may be usable. Inspect track states and continue polling. |
completed | Read the sources and requested tracks. Stop polling. |
failed | Stop polling for success and inspect the error guide. |
A quick search without analysis usually finishes in seconds; with the default medium analysis it can take a minute or two. A deep search reads 15 sources in full and usually takes about three minutes, so poll it less often or use a webhook.
POST returns queued after Redis confirms the search and queue entry. A separate worker changes it to running, then completed or failed. GET may skip over short-lived states between polls. Intermediate track progress is not published yet.
The worker has a 10-minute execution timeout by default, starting when work begins, excluding time in the queue. A handled timeout becomes failed; provider work is not automatically retried. If a search stays queued, check that the worker is running with the same Redis connection and queue as the API. /health checks Redis, not worker availability.
Track states are different
The document and each claim use pending, running, done, or failed. A claim with searched: false can remain pending when the overall search is complete. This means the claim was identified but not searched under the current claim cap.
Track scores are keyed by source ID and reflect that track's ranking. Prefer them to Source.score when a source occurs in more than one track.
Poll without creating new work
GET reads stored results and does not call search providers again, and polling never costs credits. Use a bounded polling loop; the quickstart uses two seconds as an example interval, not a documented rate entitlement.
If you lose a create response, the current API has no implemented idempotency-key protection. Repeating POST may start another search. Planned idempotency and rate controls will be documented when implemented.
Retention
Searches are shared in Redis. Completed and failed results are retained for one hour from completion by default. GET does not extend retention. Different API processes using the same Redis namespace can read them, including after an API restart.
Queued records have a one-hour TTL, reset when execution is claimed. Queued work survives an API restart. Worker failure callbacks record a failed outcome when Redis is reachable, but loss of the whole worker or Redis can leave a running record until this window expires; automatic recovery is not implemented. Late writes cannot restore expired or deleted records.
Expired, deleted or lost IDs return 404 job_not_found; no tombstone or public expires_at field is implemented yet. Redis outages return 503 cache_unavailable. A cache miss never restarts the search. Retention is configurable by the deployment; these durations describe the current defaults.