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 to one of your workspaces. 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 can use the remaining retries after a retryable failure. There is no total retry budget by default; an explicit budget can prevent a retry after a long attempt. 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.