Skip to content

Tasks and results

View Markdown

This reference describes the available Job Search API contract.

Task lookup returns { "task": ... }. Submission and cancellation return { "receipt": ..., "task": ... }; the current task can be null while its command certainty remains recorded. A task includes taskId, productId, status, createdAt, finishedAt, deadline, input, sources, contract, billing, initiatedBy, resultCount, sourceOutcomes, notices, coverageTruncated, resultExpiresAt, resultAvailability, failureCode and retryAfterSeconds.

Status Meaning
queued, running, finalizing, retry_wait Work is in progress. Results are not yet available.
succeeded Accepted records have been committed. This is not a claim that all jobs at the source were collected.
partial Usable records were committed with an incomplete source scope, as authorized by allowPartial.
empty Completed scope yielded no accepted records; no collection charge.
failed, expired, cancelled No result delivery; the reservation is released.

GET /v1/tasks/{taskId} can return HTTP 200 for any task state. Inspect status, not just HTTP success. failureCode provides the task failure reason when applicable. sourceOutcomes and coverageTruncated identify coverage limits and are null before a receipt exists.

notices contains at most 50 collection status lines, each with level (info, warning or end) and a message of at most 300 characters. An empty array means no notices are currently supplied. Keep the level and render messages as untrusted text. Unsupported optional filters may be reported here.

Retained task input is the frozen JSON submitted under that task’s schema version. Historical tasks may contain earlier fields. To start new work, construct an input using the current Job Search contract and obtain a new quote.

billing.reservedUnits and billing.chargedUnits are decimal strings, with 1,000,000 units per credit. A terminal task has no remaining reservation. contract records the accepted schema version, price version and total record limit across selected platforms.

The task response includes billing.reservationTotalUnits, the original accepted reservation, and billing.releasedUnits, the amount released from that reservation. A missing or null value means the breakdown is unavailable; do not treat it as zero.

For example, a task that initially reserved 10 credits and delivered 6 chargeable records at 1 credit each finishes with 0 reserved, 6 charged and 4 released. While a task is active, released units remain zero. Cancellation, expiry or failure without delivery releases the full reservation. Internal validation tasks reserve and charge zero.

When the full breakdown is known, reservationTotalUnits = reservedUnits + chargedUnits + releasedUnits. Use integer arithmetic on the decimal strings. Later refunds or result-loss compensation are separate ledger entries and do not rewrite this task’s original charge or release.

The task response includes startedAt, the database timestamp when the first execution attempt was allocated. It stays fixed across retries. This includes preparation before collection; it is not a timestamp from the source website or proof that the collector has started a network request.

startedAt is null before an attempt is allocated or when the first attempt’s historical evidence is unavailable. Do not substitute a later retry, the creation time or the current time. createdAt to finishedAt remains the total task duration, including queue time and retries. The existing deadline field is the task’s execution deadline.

The task contract includes nullable progress while a task is running or finalizing. It contains the current attempt, phase (candidates, details or packaging), sourcesFinished, sourcesTotal, candidatesSeen, detailsProcessed, recordsMatched and receivedAt.

These are provisional observations from the collector. sourcesFinished counts processed candidate lists, including failed checks. Matching records can still fail validation or be discarded before delivery. Use the final receipt’s resultCount and billing fields for delivered records and charges. There is no completion percentage or estimated finish time.

receivedAt is when the API received the report; collection happened earlier, and a slow source may leave the counts unchanged. Missing observations are null, not zero. A new attempt clears the previous observation; queued, retrying and terminal tasks return null. This data does not extend the task deadline or result retention.

The task contract includes links to task responses from REST, Console and MCP. Each relation contains href and method:

Relation Method Purpose
self GET Read the current task state.
results GET Read a result page, with optional fields and view parameters.
download POST Request download delivery; send a JSON body such as {"format":"jsonl"}.
cancel POST Request cancellation with full-access credentials. A completed task stays final.

Resolve these paths against your configured API origin, including when the task came from Console or MCP. They contain no credentials or signed storage tokens. Supply the credentials required by the API; the presence of a link does not grant permission or promise that results are ready. Results can still return 409 RESULT_NOT_AVAILABLE or 410 RESULT_EXPIRED / RESULT_LOST. Follow a new task read to see the current state. Obtaining a link never starts another collection.

GET /v1/tasks/{taskId}/results returns data and meta, containing resultCount and pagination: { hasMore, nextCursor, prevCursor }. It does not embed records inside the task response. The default page size is 100. Optional pageSize is 1–1,000; a byte limit can produce a shorter page. Always follow hasMore and nextCursor.

Use fields=title,companyName,platformUrl to select fields. Keep the same field selection when continuing with a cursor. Cursors are opaque and bound to the account, task and saved snapshot. Pagination reads existing results without another collection or charge. Records follow the Job Search output schema, including nullable structured fields.

resultAvailability is available, not_ready, expired or lost. Once resultExpiresAt passes, result reads return 410 RESULT_EXPIRED; the task itself can still be inspected. A new collection requires a new request and budget.

Result reads support format=markdown for bounded model consumption. The default remains format=json, with complete projected records.

For example, read /v1/tasks/{taskId}/results?format=markdown&fields=recordId,title,description&maxItems=20&maxChars=12000. The response contains data fragments with markdown, offset, nextOffset and complete. Each fragment labels collected text as untrusted source data and presents it as indented JSON text. Source instructions do not authorize tool calls or spending.

Option Markdown behavior
fields Select from the product’s advertised modelView.fields. Keep the selection unchanged on continuation.
maxItems Maximum fragments per response: default 20, up to 100. If pageSize is also supplied, both values must agree.
maxChars Maximum Unicode code points across the markdown strings, including labels and indentation: default 12,000, from 512 to 64,000. JSON envelope bytes are additional. This option is rejected for JSON format.

meta.modelView.truncated means more text or records remain. Continue with meta.pagination.nextCursor, keeping format=markdown and the same fields. A cursor can resume inside a long record; complete=false means the record continues. Offsets count Unicode code points in that record’s projected JSON representation, before labels and indentation. Read every continuation before ranking or summarizing the entire result set. Reading never creates another collection or charge.

meta.modelView.characters counts the returned markdown characters. tokensEstimate estimates the serialized fragment array using UTF-8 bytes divided by three, rounded up; it is not model tokenizer usage or an exact context limit. The signed cursor binds the account, task, result snapshot, schema, fields, rendering version and result expiry. To change fields or format, start a new read from the same task without a cursor. Result expiry still applies during continuation.

POST /v1/tasks/{taskId}/download with {"format":"jsonl"} returns taskId, format, expiresAt and blocks. Each block contains index, bytes, count, sha256 and a signed url. URLs last at most five minutes and never beyond the result or credential expiry. Obtain fresh links from the same task if needed.

Authenticated GET /v1/tasks/{taskId}/download.csv returns a CSV stream of the same saved records. Spreadsheet formula prefixes are neutralized. An interrupted stream is not a complete file; retry from the saved task.

GET /v1/tasks returns items and meta.pagination. Optional filters are productId, status, createdAfter and createdBefore; pageSize and cursor control pagination. Keep filters unchanged while paging.

POST /v1/tasks/{taskId}/cancel requests cancellation and requires full-access credentials, an empty JSON body and a canonical command key. A terminal task remains unchanged; inspect this cancel command’s own receipt. Cancellation racing a successful commit may return the already completed task; inspect the returned state.

See API conventions and errors and recovery.