Perception
Sources
Every tool takes a source, typed SourceInput: a Source object, or a plain string.
source | Type | What it is |
|---|---|---|
"https://..." | string | A public HTTPS link, sent as a url source with a file_name taken from the URL. |
{ type: "url", url, file_name? } | UrlSource | A public HTTPS link the document service downloads. file_name is taken from the URL when you leave it out. |
{ type: "workspace_file", workspace_id, file_id } | WorkspaceFileSource | A file you uploaded. workspaceFile(file) builds it from what documents.upload returns. |
{ type: "parse_result", job_id } | ParseResultSource | One of your finished parse jobs, so Parse, Split, Extract and Ground reuse it instead of parsing the document again. Classify doesn't take it. |
Source is the union of the three objects. workspaceFile(file) returns the WorkspaceFileSource for an UploadedFile, which documents.upload and completeUploadSession return.
A URL source needs a file_name: the document service picks the parser from its extension, and refuses a type the tool can't read (see Format support). When you leave it out, the SDK takes the URL's last path segment, without its query or fragment and percent-decoded, as long as that segment has an extension: https://example.com/files/Q3%20report.pdf?dl=1 sends Q3 report.pdf. Otherwise it throws a NaceError before sending, and you pass the name yourself. A file_name you pass is sent as it is.
A string that isn't an https:// URL throws a NaceError; http:// links aren't accepted.
// The last segment here isn't a file name: the SDK would send "1706.03762", which the service refuses.
await client.documents.parse({
source: { type: "url", url: "https://arxiv.org/pdf/1706.03762", file_name: "attention.pdf" },
});Create a job
The five tools each take one params object and return APIPromise<DocumentJob>. These parameters are shared:
| Parameter | Type | Required | Description |
|---|---|---|---|
source | SourceInput | Yes | The document. See Sources. |
wait_seconds | number | No | Hold the request open until the job finishes, 0 to 60 (MAX_WAIT_SECONDS). The attempt's timeout grows by as much. Out of range throws a NaceError. |
idempotency_key | string | No | Up to 200 characters. The same key and body return the same job, billed once. Minted per call when omitted. |
name | string | No | A display name for the job. |
project_id | string | No | A UUID you mint to group jobs you submit together. |
Every other field goes to the document service as it is, and a field it doesn't know, a misspelled one included, is refused with 422. CreateParams is the shared type; ClassesParams, ExtractParams and GroundParams add each tool's own fields.
The job comes back queued or running, or finished when wait_seconds was long enough. Wait for the rest with jobs.wait:
const created = await client.documents.parse({
source: "https://example.com/report.pdf",
wait_seconds: 60,
});
const job = created.status === "succeeded" ? created : await client.jobs.wait(created.job_id);
console.log(job.result);Retries. The minted key stays the same across the SDK's own retries, so they never start or bill a second job. To retry a create yourself, after the SDK's retries ran out, after a 503 job_pending or after a restart, pass your own idempotency_key and send it again. When a create fails after the SDK's retries, the error's idempotencyKey is the key it sent, so after a 503 job_pending you can send the same body again with idempotency_key: error.idempotencyKey to resume the job. See Retry safely.
A create that holds the request open is retried like any other call, but the default retry budget is 30 seconds in all, so an attempt that fails after waiting longer than that isn't retried. Raise retry.timeoutMs to retry those; see Retries.
The charge's id. A create's x-drex-document-job header carries Drex's own id for the charge. Quote it with the request id when you contact support:
const { data: job, response, requestId } = await client.documents
.parse({ source: "https://example.com/report.pdf" })
.withResponse();
console.log(job.job_id, response.headers.get("x-drex-document-job"), requestId);Parse, Split, Classify and Extract take page_ranges as Array<{ start: number; end: number }>: one-based and inclusive, at most 200 ranges and 500 pages in all.