Document Scan / OCR (totalum-sdk/scan)
import … from 'totalum-sdk/scan' — or the same namespace on totalum from 'totalum-sdk'. Install, configuration and errors: Totalum SDK.
Read documents and images: extract the fields you describe (an invoice's number, date and total) as JSON with
document(), or get the plain text of every page with ocr(). The document can be a project file, a URL or a
file name of the project. Billed in credits.
const { data } = await totalum.scan.document({
key: invoice.key,
properties: { total: { type: 'number', description: 'the invoice total' } },
});| Method or type | What it does |
|---|---|
totalumScan | Creates the scan namespace (the same object as totalum.scan, scope scan): documents and images read by a vision model. |
scan.document | Reads a document or image (a PDF, a photo, a scan) and returns the fields you describe — an invoice's number, date and total, an ID card's name — as JSON. |
scan.ocr | The text of a document or image (OCR), as Markdown per page, keeping reading order and tables. |
ScanDocumentInput | The input of scan.document(): one document and the fields to extract. |
ScanDocumentResult | What scan.document() returns: the extracted fields (one set per page with processEveryPdfPageAsDifferentScan), details of the scan, and what it cost. |
ScanOcrInput | The input of scan.ocr(): one document. |
ScanOcrOutput | The text of a document, from scan.ocr(). |
#totalumScan
totalumScan(options?: TotalumClientOptions): TotalumScanCreates the scan namespace (the same object as totalum.scan, scope scan): documents and images read by a
vision model.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
options | TotalumClientOptions | no | The project key, API URL and environment; each falls back to its environment variable. |
options.key | string | no | Project key tlm_pk_…; default TOTALUM_PROJECT_KEY. Server-side only. |
options.apiUrl | string | no | The Totalum API's URL: default TOTALUM_SDK_API_URL, else https://sdk-api.totalum.app. |
options.env | 'dev' | 'live' | no | Sent as x-totalum-env on every call (the database it targets, and dev vs live usage); default TOTALUM_ENV, else live. |
Returns TotalumScan — The scan namespace: the methods below.
Example
import { totalumScan } from 'totalum-sdk/scan';
const scan = totalumScan();
const { text } = await scan.ocr({ key: 'p/acme-crm/01M4P0SFVZXNRS871ZSKZNWHY0.png' });The namespace's type is exported as TotalumScan (import type { TotalumScan } from 'totalum-sdk/scan').
#scan.document
scan.document(input: ScanDocumentInput): Promise<ScanDocumentResult>Reads a document or image (a PDF, a photo, a scan) and returns the fields you describe — an invoice's number,
date and total, an ID card's name — as JSON. Describe each field with a JSON Schema type and a description;
fields not found are null. Pass exactly one of key, fileName or url.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
input | ScanDocumentInput | yes | The document and the fields to extract. |
input.properties | Record<string, Record<string, unknown>> | yes | The fields to extract, as JSON Schema properties: { total: { type: "number", description: "the invoice total" } }. A good description gives better results. |
input.options | { model?, removeFileAfterScan?, returnOcrFullResult?, scanDescription?, processEveryPdfPageAsDifferentScan?, maxPages?, pdfPages?, minimumConfidence? } | no | How the document is read. |
input.options.model | 'scanum' | 'scanum-pro' | 'scanum-eye' | 'scanum-eye-pro' | no | scanum / scanum-eye (default: the fast vision model) or scanum-pro / scanum-eye-pro (the smarter model, for hard documents). |
input.options.removeFileAfterScan | boolean | no | Accepted for compatibility; has no effect (delete the file with files.delete). |
input.options.returnOcrFullResult | boolean | no | Accepted for compatibility; has no effect (use scan.ocr for the text). |
input.options.scanDescription | string | no | What the document is, in words (a Spanish electricity bill): helps the model. |
input.options.processEveryPdfPageAsDifferentScan | boolean | no | true extracts the fields once per page (data is then an array): a PDF of many receipts. |
input.options.maxPages | number | no | Accepted for compatibility; has no effect. Allowed: > 0, ≤ 200. |
input.options.pdfPages | number[] | no | Accepted for compatibility; has no effect. |
input.options.minimumConfidence | number | no | Accepted for compatibility; has no effect. Allowed: ≥ 0, ≤ 1. |
input.fileName | string | no | Same as key (the name of the first scan API). |
input.key | string | no | The document as a project file key (a PDF or an image). |
input.url | string | no | The document as a URL (a public https:// URL, or a project file URL). Allowed: a URL. |
Returns Promise<ScanDocumentResult> — The extracted fields, details of the scan, and what it cost.
| Field | Type | Always present | Description |
|---|---|---|---|
data | Record<string, unknown> | (Record<string, unknown>)[] | yes | The fields you described in properties, with the values read from the document (null when absent); an array of them, one per page, with processEveryPdfPageAsDifferentScan. |
metadata | { usageUnits, exactUsageUnits, pages, provider, credits } | yes | Details of the scan, kept in the shape of the first scan API. |
metadata.usageUnits | number | yes | Pages read. |
metadata.exactUsageUnits | number | yes | Same as usageUnits. |
metadata.pages | number | yes | Pages in the document. |
metadata.provider | string | yes | Always 'totalum'. |
metadata.credits | number | yes | Same as usage.credits. |
usage | { credits } | yes | What the scan cost. |
usage.credits | number | yes | Credits charged for this call. |
Errors — besides the errors every call can throw:
| Code | HTTP | When |
|---|---|---|
UNSUPPORTED_FILE_TYPE | 400 | The file is not a PDF or an image. |
FILE_NOT_FOUND | 404 | No file with this key. |
FILE_KEY_FORBIDDEN | 403 | The key belongs to another project. |
FILE_TOO_LARGE | 413 | The file is over the plan's largest file. |
URL_NOT_ALLOWED | 400 | The url is not a public http(s) URL. |
SCAN_DOCUMENT_ERROR | 502 | The document could not be read; retry, or try model: 'scanum-pro'. |
Example
const scan = await totalum.scan.document({
key: invoice.key,
properties: {
invoiceNumber: { type: 'string', description: 'the invoice number' },
issueDate: { type: 'string', description: 'the issue date as YYYY-MM-DD' },
total: { type: 'number', description: 'the total amount including tax' },
},
});Result:
{
"data": { "invoiceNumber": "F-2026-0012", "issueDate": "2026-09-30", "total": 1210 },
"metadata": { "usageUnits": 1, "exactUsageUnits": 1, "pages": 1, "provider": "totalum", "credits": 0.0039 },
"usage": { "credits": 0.0039 }
}#scan.ocr
scan.ocr(input: ScanOcrInput): Promise<{ pages, text, fullDetails?, usage }>The text of a document or image (OCR), as Markdown per page, keeping reading order and tables. Use it to index a
PDF for search, or to read a photo of a sign. Long PDFs are read in parallel chunks. Pass exactly one of key,
fileName or url.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
input | ScanOcrInput | yes | The document to read. |
input.pages | number[] | no | Accepted for compatibility; has no effect (every page is read). |
input.fileName | string | no | Same as key (the name of the first scan API). |
input.key | string | no | The document as a project file key (a PDF or an image). |
input.url | string | no | The document as a URL (a public https:// URL, or a project file URL). Allowed: a URL. |
Returns Promise<{ pages, text, fullDetails?, usage }> — The whole text, the text of each page, and what it cost.
| Field | Type | Always present | Description |
|---|---|---|---|
pages | ({ markdown, width, height, words? })[] | yes | One entry per page. |
pages.markdown | string | yes | The page's text as Markdown (tables kept). |
pages.width | number | yes | Not measured today: always 0. |
pages.height | number | yes | Not measured today: always 0. |
pages.words | ({ text, bbox })[] | no | Not returned today. |
pages.words.text | string | yes | Not returned today. |
pages.words.bbox | number[] | yes | Not returned today. |
text | string | yes | The whole text, pages separated by blank lines. |
fullDetails | unknown | no | Not returned today. |
usage | { credits } | yes | What the call cost. |
usage.credits | number | yes | Credits charged for this call. |
Errors — besides the errors every call can throw:
| Code | HTTP | When |
|---|---|---|
UNSUPPORTED_FILE_TYPE | 400 | The file is not a PDF or an image. |
FILE_NOT_FOUND | 404 | No file with this key. |
FILE_KEY_FORBIDDEN | 403 | The key belongs to another project. |
FILE_TOO_LARGE | 413 | The file is over the plan's largest file. |
OCR_PDF_PROCESSING_ERROR | 502 | A PDF could not be read. |
OCR_IMAGE_PROCESSING_ERROR | 502 | An image could not be read. |
Example
const { text, pages } = await totalum.scan.ocr({ key: 'p/acme-crm/01M4P0SFVZXNRS871ZSKZNWHY0.png' });Result:
{
"text": "TOTALUM 42",
"pages": [{ "markdown": "TOTALUM 42", "width": 0, "height": 0 }],
"usage": { "credits": 0.021 }
}#ScanDocumentInput
The input of scan.document(): one document and the fields to extract.
| Name | Type | Required | Description |
|---|---|---|---|
properties | Record<string, Record<string, unknown>> | yes | The fields to extract, as JSON Schema properties: { total: { type: "number", description: "the invoice total" } }. A good description gives better results. |
options | { model?, removeFileAfterScan?, returnOcrFullResult?, scanDescription?, processEveryPdfPageAsDifferentScan?, maxPages?, pdfPages?, minimumConfidence? } | no | How the document is read. |
options.model | 'scanum' | 'scanum-pro' | 'scanum-eye' | 'scanum-eye-pro' | no | scanum / scanum-eye (default: the fast vision model) or scanum-pro / scanum-eye-pro (the smarter model, for hard documents). |
options.removeFileAfterScan | boolean | no | Accepted for compatibility; has no effect (delete the file with files.delete). |
options.returnOcrFullResult | boolean | no | Accepted for compatibility; has no effect (use scan.ocr for the text). |
options.scanDescription | string | no | What the document is, in words (a Spanish electricity bill): helps the model. |
options.processEveryPdfPageAsDifferentScan | boolean | no | true extracts the fields once per page (data is then an array): a PDF of many receipts. |
options.maxPages | number | no | Accepted for compatibility; has no effect. Allowed: > 0, ≤ 200. |
options.pdfPages | number[] | no | Accepted for compatibility; has no effect. |
options.minimumConfidence | number | no | Accepted for compatibility; has no effect. Allowed: ≥ 0, ≤ 1. |
fileName | string | no | Same as key (the name of the first scan API). |
key | string | no | The document as a project file key (a PDF or an image). |
url | string | no | The document as a URL (a public https:// URL, or a project file URL). Allowed: a URL. |
#ScanDocumentResult
What scan.document() returns: the extracted fields (one set per page with processEveryPdfPageAsDifferentScan),
details of the scan, and what it cost.
| Field | Type | Always present | Description |
|---|---|---|---|
data | Record<string, unknown> | (Record<string, unknown>)[] | yes | The fields you described in properties, with the values read from the document (null when absent); an array of them, one per page, with processEveryPdfPageAsDifferentScan. |
metadata | { usageUnits, exactUsageUnits, pages, provider, credits } | yes | Details of the scan, kept in the shape of the first scan API. |
metadata.usageUnits | number | yes | Pages read. |
metadata.exactUsageUnits | number | yes | Same as usageUnits. |
metadata.pages | number | yes | Pages in the document. |
metadata.provider | string | yes | Always 'totalum'. |
metadata.credits | number | yes | Same as usage.credits. |
usage | { credits } | yes | What the scan cost. |
usage.credits | number | yes | Credits charged for this call. |
#ScanOcrInput
The input of scan.ocr(): one document.
| Name | Type | Required | Description |
|---|---|---|---|
pages | number[] | no | Accepted for compatibility; has no effect (every page is read). |
fileName | string | no | Same as key (the name of the first scan API). |
key | string | no | The document as a project file key (a PDF or an image). |
url | string | no | The document as a URL (a public https:// URL, or a project file URL). Allowed: a URL. |
#ScanOcrOutput
The text of a document, from scan.ocr().
| Field | Type | Always present | Description |
|---|---|---|---|
text | string | yes | The whole text, pages separated by blank lines. |
pages | ({ markdown, width, height, words? })[] | yes | One entry per page. |
pages.markdown | string | yes | The page's text as Markdown (tables kept). |
pages.width | number | yes | Not measured today: always 0. |
pages.height | number | yes | Not measured today: always 0. |
pages.words | ({ text, bbox })[] | no | Not returned today. |
pages.words.text | string | yes | Not returned today. |
pages.words.bbox | number[] | yes | Not returned today. |
fullDetails | unknown | no | Not returned today. |
