{"components":{"responses":{"DocumentExpired":{"content":{"application/json":{"example":{"error":{"message":"The document has expired and its results were purged.","type":"document_expired"}}}},"description":"Retention ran out and the result was purged"},"DocumentNotReady":{"content":{"application/json":{"example":{"error":{"message":"The document is processing; queries need a completed document.","status":"processing","type":"document_not_ready"}}}},"description":"The document has not finished processing"},"InsufficientCredits":{"content":{"application/json":{"example":{"error":{"balance_micro":0,"message":"Your workspace has no credits left.","top_up_url":"https://northdoc.northcape.tech/app/acme-robotics/billing","type":"insufficient_credits"}}}},"description":"No credits left, or (for an upload) not enough for its estimated\ncost. A URL document or a question whose estimate the credit cannot\ncover is accepted and then fails with `error.type: insufficient_credits`.\n"},"InvalidRequest":{"content":{"application/json":{"example":{"error":{"details":{"markdown":["requires analysis \"layout\""]},"message":"Invalid options.","type":"invalid_request"}}}},"description":"Body or options failed validation (`details` lists the fields), or the document is too large (`document_too_large`)"},"NotFound":{"content":{"application/json":{"example":{"error":{"message":"No such document.","type":"not_found"}}}},"description":"No document or query with that id for this key (documents are scoped to the key's workspace and live/test mode)"},"PayloadTooLarge":{"content":{"application/json":{"example":{"error":{"message":"The file is 25000000 bytes; your plan allows up to 20000000 bytes per document.","type":"payload_too_large"}}}},"description":"The file is over the plan's upload limit (or the request body over the server limit)"},"QuotaExceeded":{"content":{"application/json":{"example":{"error":{"limit":10000,"message":"Monthly request quota exhausted.","resets_at":"2026-10-01T00:00:00Z","type":"quota_exceeded","upgrade_url":"https://northdoc.northcape.tech/app/acme-robotics/billing","used":10000}}}},"description":"Payment required. Either the plan's monthly request quota is spent\n(`quota_exceeded`, trial plans only — pay as you go is never capped)\nor the workspace is out of credit (`insufficient_credits`).\n"},"RateLimited":{"content":{"application/json":{"example":{"error":{"limit":2,"message":"Too many requests. Limit is 2 per second.","retry_after":1,"type":"rate_limited"}}}},"description":"Per-second burst limit for the plan exceeded; retry after `Retry-After` seconds"},"Unauthorized":{"content":{"application/json":{"example":{"error":{"message":"Missing or invalid API key.","type":"unauthorized"}}}},"description":"Missing, revoked or expired key"},"UnsupportedMediaType":{"content":{"application/json":{"example":{"error":{"message":"Unsupported file type. Send a PDF, PNG, JPEG, TIFF, BMP, HEIF, DOCX, XLSX or PPTX.","type":"unsupported_media_type"}}}},"description":"Not a PDF, PNG, JPEG, TIFF, BMP, HEIF, DOCX, XLSX or PPTX"}},"schemas":{"Accepted":{"description":"What `POST /documents` answers with. A batch answers `{\"documents\": [...]}` with one of these (or an `error`) per file, in order.","properties":{"estimated_cost_micro":{"description":"Credit held while it runs, in micro-USD. You are charged the real cost at the end. `null` for a URL until it has been downloaded.","type":"integer"},"id":{"description":"The document's id. Keep it: every other call needs it.","type":"string"},"object":{"const":"document","description":"Always `document`.","type":"string"},"poll_url":{"description":"Where to check on it: `GET /documents/{id}`.","type":"string"},"status":{"description":"`queued`: it has not started yet.","type":"string"}},"type":"object"},"Account":{"properties":{"credits":{"description":"What the workspace can spend.","properties":{"available_micro":{"description":"Credit available now, in micro-USD (25000000 is US$25).","type":"integer"}},"type":"object"},"key":{"description":"The key that made the call. Only a prefix of it, never the secret.","properties":{"id":{"type":"string"},"mode":{"enum":["live","test"],"type":"string"},"name":{"type":"string"},"prefix":{"type":"string"}},"type":"object"},"limits":{"description":"What one document may be on this plan.","properties":{"max_concurrent_jobs":{"description":"Documents processed at once; more wait in the queue.","type":"integer"},"max_pages_per_document":{"description":"More pages is a 422.","type":"integer"},"max_retention_seconds":{"description":"The longest `retention_seconds` allowed; `0` means no limit.","type":"integer"},"max_upload_bytes":{"description":"A bigger file is a 413.","type":"integer"}},"type":"object"},"organization":{"description":"The workspace the key belongs to.","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"type":"object"},"plan":{"description":"The workspace's plan.","properties":{"id":{"type":"string"},"name":{"type":"string"}},"type":"object"},"rate_limit_per_second":{"description":"Requests allowed per second.","type":"integer"}},"type":"object"},"Document":{"description":"What `GET /documents/{id}` returns. Lists return the same object\nwithout `result`. Times are ISO 8601 in UTC. Money is in micro-USD\n(1,000,000 = US$1).\n","properties":{"analysis":{"description":"The `analysis` option it ran with.","enum":["layout","read"],"type":"string"},"byte_size":{"description":"File size in bytes.","type":"integer"},"completed_at":{"description":"When it finished.","format":"date-time","type":"string"},"content_type":{"description":"The type detected from the file's bytes, e.g. `application/pdf`.","type":"string"},"cost":{"description":"`estimated_micro` was held from your credit when it was accepted; `settled_micro` is what it actually cost, once finished.","properties":{"estimated_micro":{"description":"Held before processing","type":"integer"},"settled_micro":{"description":"Charged after processing","type":"integer"}},"type":"object"},"created_at":{"description":"When you submitted it.","format":"date-time","type":"string"},"error":{"description":"Present when `status` is `failed`. `type` is one of\n`analysis_failed`, `fetch_failed`, `unsupported_media_type`,\n`payload_too_large`, `document_too_large`, `schema_mismatch`,\n`insufficient_credits`, `embedding_failed` or `processing_failed`\n(anything else). `stage` is the step it failed at. A failed document\nkeeps answering `200` with its `error`; only an expired one answers\n`410`. You pay only for the work done\nbefore it failed.\n","properties":{"message":{"type":"string"},"stage":{"type":"string"},"type":{"type":"string"}},"type":"object"},"expires_at":{"description":"When the result will be deleted (`completed_at` + `retention_seconds`); `null` if kept forever.","format":"date-time","type":"string"},"failed_at":{"description":"When it failed.","format":"date-time","type":"string"},"filename":{"description":"The uploaded file's name, or the last part of the URL.","type":"string"},"id":{"description":"The document's id. Keep it: every other call needs it.","type":"string"},"markdown":{"description":"With `include=markdown` and the `markdown` output: the document as markdown.","type":"string"},"mode":{"description":"`test` when made with an `ak_test_…` key: fake results, no charge.","enum":["live","test"],"type":"string"},"model":{"description":"`requested` is the `model` option you sent; `used` is the model and version that actually read it, such as `northdoc-swift-1`.","properties":{"requested":{"type":"string"},"used":{"type":"string"}},"type":"object"},"object":{"const":"document","description":"Always `document`.","type":"string"},"options":{"$ref":"#/components/schemas/DocumentOptions","description":"With `include=options`: the options it was sent with, defaults filled in."},"page_count":{"description":"Number of pages (the real count once analysed).","type":"integer"},"pages":{"description":"With `include=pages`: one object per page.","items":{"$ref":"#/components/schemas/DocumentPage"},"type":"array"},"purged_at":{"description":"When the result was deleted.","format":"date-time","type":"string"},"result":{"$ref":"#/components/schemas/ExtractionResult","description":"What the model produced, once `status` is `completed`: `null` unless the document was sent with an `extraction` or `queries`. See `ExtractionResult`."},"retention_seconds":{"description":"How long the result is kept after completing (`0` = forever).","type":"integer"},"retrieved_at":{"description":"The first time you fetched the completed result.","format":"date-time","type":"string"},"source_url":{"description":"The URL you sent, for URL uploads; otherwise `null`.","type":"string"},"stage":{"description":"The step it is on, in order: `received`, `fetching` (URL uploads\nonly), `analyzing` (OCR and layout), `rendering` (pictures of\nfigures and scanned pages), `reserving` (credit hold re-sized),\n`extracting` (the model reads it), `embedding` (only with the\n`embeddings` output), `finalizing`, then `done`. Steps with nothing\nto do are skipped.\n","enum":["received","fetching","analyzing","rendering","reserving","extracting","embedding","finalizing","done"],"type":"string"},"started_at":{"description":"When a worker picked it up.","format":"date-time","type":"string"},"status":{"description":"Where it is overall: `queued` (waiting for a worker), `processing`,\nthen `completed` (read `result`) or `failed` (read `error`).\n`expired` means retention ran out and the result was deleted.\n","enum":["queued","processing","completed","failed","expired"],"type":"string"},"text":{"description":"With `include=text`: the text the model read, each page under a `=== Page N ===` line, after any OCR key/value hints.","type":"string"},"timings":{"additionalProperties":{"type":"integer"},"description":"Milliseconds spent on each step, e.g. `analyzing_ms`.","type":"object"},"usage":{"description":"With `include=usage`: what this document and its queries cost, in total, per SKU and per record.","properties":{"amount_micro":{"type":"integer"},"by_sku":{"additionalProperties":{"properties":{"amount_micro":{"type":"integer"},"quantity":{"type":"integer"}},"type":"object"},"description":"Per SKU: the quantity (pages or tokens) and what it cost.","type":"object"},"records":{"items":{"$ref":"#/components/schemas/UsageRecord"},"type":"array"}},"type":"object"}},"type":"object"},"DocumentOptions":{"description":"Processing options. Every one is optional, and with none at all the\ndocument is read and its pictures taken, nothing more: no AI model runs\nand `result` is `null`. Switch on what you need: `embeddings`,\n`markdown`, an `extraction` or `queries`. The model runs only for an\n`extraction` or `queries`.\n\nIn a `multipart/form-data` request this whole object is sent as a JSON\n**string** in the `options` part. In the JSON body form it is a nested\nobject.\n","example":{"embeddings":true,"extraction":{"fields":["summary","parties"],"instructions":"total is the amount payable after tax.","schema":{"properties":{"invoice_number":{"type":"string"},"total":{"type":"number"}},"required":["invoice_number","total"],"type":"object"}},"queries":["What is the total amount due?"],"retention_seconds":3600},"properties":{"analysis":{"default":"layout","description":"How the pages are read. `layout` ($0.025/page) also finds tables,\nkey/value pairs, figures and reading order. `read` ($0.004/page) is\nOCR only, about six times cheaper: pages come back without tables,\nkey/value pairs or figures, and `markdown: true` with it is a 422.\nExample: `\"analysis\": \"read\"`.\n","enum":["layout","read"],"type":"string"},"embeddings":{"allOf":[{"$ref":"#/components/schemas/EmbeddingOptions"}],"description":"Make a vector for every page, for your own search or model. Off\nunless you send it: `true` for the defaults (one 1,024-number\nvector per page), or an object to choose the settings. Billed as\n`compass.input`. Read them from\n`GET /documents/{id}/pages?include=embeddings`.\nExample: `\"embeddings\": true`.\n","x-type":"true | EmbeddingOptions"},"extraction":{"allOf":[{"$ref":"#/components/schemas/ExtractionOptions"}],"description":"Have the model fill `result.data`: any of Northdoc's built-in\n`fields` (summary, parties, dates and more), your own JSON\n`schema`, or both. Off unless you send it. Name at least one field\nor give a schema.\nExample: `\"extraction\": {\"fields\": [\"summary\", \"parties\"]}`.\n"},"images":{"default":true,"description":"Take pictures of the document: figures (charts, diagrams, photos)\nare cropped from their pages, and a whole page is kept when\npictures cover at least half of it or it has fewer than 25 words\n(scans, signature and stamp pages, handwriting). Tiny figures\n(under 1.5% of the page, like logos) and blank pages are skipped.\nDownload them with `GET /documents/{id}/images`, or with each page\nfrom `GET /documents/{id}/pages?include=image_data`. Covered by the\npage price.\n\nWhen the model runs it reads the pictures where they sit in the\ntext. They are billed as input tokens then (about\nwidth × height / 750 each, at most ~1,600); one request carries at\nmost 20 images and 10 MB, and past that the largest are kept and\n`result.warnings` says how many were left out.\n\nWorks on PDFs, and on PNG and JPEG uploads (under 3.75 MB and\n8000px, kept as the page image). TIFF, BMP, HEIF and Office files\nhave no pictures taken. `false` takes none.\nExample: `\"images\": false`.\n","type":"boolean"},"markdown":{"default":false,"description":"Also produce a markdown rendering of the whole document, read with\n`GET /documents/{id}?include=markdown`. Needs `analysis: layout`.\nSame page price.\nExample: `\"markdown\": true`.\n","type":"boolean"},"model":{"default":"auto","description":"Which Northdoc model reads the document, when one runs (for an\n`extraction` or `queries`).\n\n* `swift` — fast and economical, for everyday documents up to about\n  180k tokens (roughly 300 pages of dense text).\n* `summit` — the most capable, for long or dense legal and financial\n  documents, up to about 900k tokens.\n* `auto` (the default) — `swift` up to about 150k tokens, `summit`\n  beyond that.\n\nPin `summit` when accuracy on hard documents matters most; pin\n`swift` to cap cost. A document too long for `swift` is accepted,\nread and charged for its pages, then fails at `extracting` with\n`error.type: document_too_large`; `auto` moves to `summit` instead. `model.used` on the document says which\none ran (`northdoc-swift-1` or `northdoc-summit-1`).\n\nSwift and Summit are kept current: when a better model becomes\navailable the name moves to it and the version in `model.used`\ngoes up (`northdoc-swift-2`), with no change to the API.\nExample: `\"model\": \"summit\"`.\n","enum":["auto","swift","summit"],"type":"string"},"queries":{"description":"Questions the model answers while the document is processed,\nreturned in order under `result.answers`. Each question once: the\nsame question twice is a 422. Cheaper than one\n`POST /documents/{id}/queries` per question because the document is\nread once for all of them. Use the queries endpoint for follow-ups\nyou only think of later.\nExample: `\"queries\": [\"What is the total?\", \"When is it due?\"]`.\n","items":{"maxLength":2000,"type":"string"},"maxItems":50,"type":"array"},"retention_seconds":{"default":86400,"description":"How long results are kept once the document completes:\n`expires_at` is `completed_at` plus this many seconds. A result you\nhave never fetched is kept for at least 24 hours after it completes,\nhowever short this is, so a short retention never deletes a result\nnobody has read. Reading a result does not move `expires_at`.\n\n`0` means keep indefinitely, which only plans with\n`limits.max_retention_seconds == 0` may do; on capped plans `0` is\nclamped to the plan limit and anything larger is a 422. Read the\nceiling from `GET /account`. After it lapses the document returns\n`410 document_expired`.\nExample: `\"retention_seconds\": 3600`.\n","minimum":0,"type":"integer"}},"type":"object"},"DocumentPage":{"description":"One page, from `GET /documents/{id}/pages` or `include=pages`.","properties":{"embedding":{"description":"With `include=embeddings`: the page's vector, the model that made it and its length.","properties":{"dimensions":{"type":"integer"},"model":{"type":"string"},"vector":{"items":{"type":"number"},"type":"array"}},"type":"object"},"images":{"description":"With `include=images` or `include=image_data`: the page's pictures, in their order on the page (with `image_data`, bytes included).","items":{"$ref":"#/components/schemas/Image"},"type":"array"},"key_values":{"additionalProperties":{"type":"object"},"description":"With `include=key_values`: labelled fields the OCR found, each with its `value`, `key_confidence` and `value_confidence` (0 to 100), and `selection_status` (`SELECTED` or `NOT_SELECTED` for a checkbox, otherwise `null`).","type":"object"},"layout":{"description":"With `include=layout`: raw layout elements (headings, paragraphs, tables, figures) with their positions on the page.","items":{"type":"object"},"type":"array"},"page":{"description":"Page number, starting at 1.","type":"integer"},"result":{"description":"With `extraction.per_page`: this page's own `data` and `citations`; otherwise `null`.","type":"object"},"tables":{"description":"With `include=tables`: each table's size and a markdown copy.","items":{"properties":{"columns":{"type":"integer"},"markdown":{"type":"string"},"rows":{"type":"integer"}},"type":"object"},"type":"array"},"text":{"description":"The page's text in reading order. Tables are markdown; each figure is a `[FIGURE]` marker.","type":"string"},"word_count":{"description":"Words the OCR found on the page.","type":"integer"}},"type":"object"},"EmbeddingOptions":{"description":"Vector settings, under `embeddings` in `DocumentOptions`; `\"embeddings\":\ntrue` takes all the defaults. Vectors come from Northdoc's Compass model\nand are billed as `compass.input` per token.\n","example":{"dimensions":1024,"granularity":"page"},"properties":{"dimensions":{"default":1024,"description":"Vector length. Compass is trained so shorter vectors stay usable:\n512 and 256 cut storage and index size at a small accuracy cost.\nPick one per corpus — you cannot compare vectors of different\nlengths. Example: `\"dimensions\": 256`.\n","enum":[1024,512,256],"type":"integer"},"granularity":{"default":"page","description":"`page` embeds each page as one vector (from up to its first 20,000\nbytes of text), returned by\n`GET /documents/{id}/pages?include=embeddings`.\n","enum":["page"],"type":"string"}},"type":"object"},"Error":{"properties":{"error":{"properties":{"message":{"type":"string"},"type":{"enum":["unauthorized","forbidden","not_found","rate_limited","quota_exceeded","not_entitled","invalid_request","insufficient_credits","document_not_ready","document_expired","conflict","payload_too_large","unsupported_media_type","document_too_large","internal_error"],"type":"string"}},"required":["type","message"],"type":"object"}},"type":"object"},"ExtractionOptions":{"description":"What the model fills `result.data` with. Sits under `extraction` in\n`DocumentOptions`. Name at least one built-in field or give a schema;\nwith both, they share `result.data`, so a schema property cannot have\nthe same name as a field you ask for.\n","example":{"fields":["summary","dates"],"instructions":"Amounts are in the document's own currency; do not convert.","per_page":false,"schema":{"properties":{"invoice_number":{"type":"string"},"line_items":{"items":{"properties":{"amount":{"type":"number"},"description":{"type":"string"}},"type":"object"},"type":"array"}},"required":["invoice_number"],"type":"object"}},"properties":{"fields":{"description":"Built-in fields, each with a fixed shape in `result.data`:\n\n* `title` — the title or heading, a string.\n* `document_type` — what kind of document it is (invoice, contract,\n  letter…), a string.\n* `summary` — two or three sentences on what it says.\n* `dates` — `[{label, date}]`, dates in ISO 8601 where possible.\n* `parties` — `[{name, role}]`, the people and organisations involved.\n* `amounts` — `[{label, amount, currency}]`, the money in it.\n* `key_facts` — the most important facts, one short sentence each.\n\nOnly the fields you name come back. A value the document does not\nconfirm is left out, never guessed.\nExample: `\"fields\": [\"summary\", \"parties\", \"dates\"]`.\n","items":{"enum":["title","document_type","summary","dates","parties","amounts","key_facts"],"type":"string"},"type":"array"},"instructions":{"description":"Free-text guidance for ambiguous fields — which of two totals to\ntake, what to do when a field is missing, how to normalise dates.\nExample: `\"instructions\": \"Use the invoice date, not the print date.\"`\n","maxLength":4000,"type":"string"},"per_page":{"default":false,"description":"Run the extraction separately on every page instead of once over the\nwhole document. Each page's result appears on that page (`result` in\n`GET /documents/{id}/pages`) as well as under `result.pages`. Costs\nroughly one extraction per page — use it for documents that are a\nstack of independent records, not for one contract spanning pages.\nUp to 200 pages; a longer document fails with\n`error.type: document_too_large`.\n","type":"boolean"},"schema":{"description":"Your own JSON Schema (`type: object`) for `result.data` to follow.\nNested objects and arrays work, so line items and tables come back\nstructured. Mark the fields you depend on as `required`.\n","type":"object"}},"type":"object"},"ExtractionResult":{"description":"What the model produced: `document.result`, once `status` is `completed`. `null` when the document was sent without an `extraction` or `queries`, because no model ran. `data` and `citations` are there with an `extraction`, `answers` with `queries`.","properties":{"answers":{"description":"One per question in `queries`, in the order you asked. `not_found: true`, with an empty `answer`, when the document does not say.","items":{"properties":{"answer":{"type":"string"},"not_found":{"type":"boolean"},"page":{"type":"integer"},"question":{"type":"string"},"quote":{"type":"string"}},"type":"object"},"type":"array"},"citations":{"description":"The citations: one per value in `data`. `path` points into `data`\n(like `data.amounts[0].amount`), `page` is where it is, `quote` is\nthe exact words it came from (or the figure's caption when only a\npicture shows it) and `confidence` runs from 0 to 1.\n","items":{"properties":{"confidence":{"type":"number"},"page":{"type":"integer"},"path":{"type":"string"},"quote":{"type":"string"}},"type":"object"},"type":"array"},"data":{"description":"The extracted data: the built-in `extraction.fields` you named, and the properties of your `extraction.schema`. A value the document does not confirm is left out, never guessed.","type":"object"},"pages":{"description":"With `extraction.per_page`: one `{page, data, citations}` per page.","items":{"type":"object"},"type":"array"},"per_page":{"description":"`true` when it ran with `extraction.per_page`. Then `pages` replaces `data` and `citations`.","type":"boolean"},"warnings":{"description":"Anything you should know about how it was read, such as images left out because the document had more than one request can carry. Absent when there is nothing to say.","items":{"type":"string"},"type":"array"}},"type":"object"},"Image":{"description":"One picture from `GET /documents/{id}/images`.","properties":{"bbox":{"description":"For a figure, where it sits on the page: `left`, `top`, `width` and `height` as fractions of the page (0 to 1). `null` for a whole page.","type":"object"},"byte_size":{"description":"File size in bytes.","type":"integer"},"caption":{"description":"The figure's caption as the OCR read it, or `null`.","type":"string"},"data":{"description":"With `include=image_data` (pages) or `include=data` (images): the file itself, base64-encoded.","type":"string"},"figure_index":{"description":"For a figure, its place among the page's `[FIGURE]` markers, from 0; `null` for a whole page.","type":"integer"},"height":{"description":"Height in pixels. The long side is at most 1568.","type":"integer"},"id":{"description":"The image's id.","type":"string"},"kind":{"description":"`figure` for a picture cropped from a page, `page` for a whole page.","enum":["figure","page"],"type":"string"},"media_type":{"description":"`image/png` (figures) or `image/jpeg` (pages).","type":"string"},"object":{"const":"image","description":"Always `image`.","type":"string"},"page":{"description":"The page it is from.","type":"integer"},"url":{"description":"Where to download the image file.","type":"string"},"width":{"description":"Width in pixels.","type":"integer"}},"type":"object"},"Query":{"description":"A question asked with `POST /documents/{id}/queries`, and its answer.","properties":{"answer":{"$ref":"#/components/schemas/QueryAnswer","description":"The answer, once `status` is `completed`. See `QueryAnswer`."},"completed_at":{"description":"When it was answered.","format":"date-time","type":"string"},"cost":{"description":"Held, then charged, in micro-USD.","properties":{"estimated_micro":{"type":"integer"},"settled_micro":{"type":"integer"}},"type":"object"},"created_at":{"description":"When you asked.","format":"date-time","type":"string"},"document_id":{"description":"The document it was asked of.","type":"string"},"error":{"description":"Why it failed.","properties":{"message":{"type":"string"},"type":{"enum":["insufficient_credits","document_too_large","document_expired","schema_mismatch","query_failed"],"type":"string"}},"type":"object"},"id":{"description":"The query's id.","type":"string"},"instructions":{"description":"The instructions you sent, if any.","type":"string"},"model":{"description":"The model you asked for and the one that answered.","properties":{"requested":{"type":"string"},"used":{"type":"string"}},"type":"object"},"object":{"const":"query","description":"Always `query`.","type":"string"},"question":{"description":"What you asked.","type":"string"},"schema":{"description":"The JSON Schema you asked the answer to follow, if any.","type":"object"},"status":{"description":"`completed` means `answer` is ready; `failed` means read `error`.","enum":["queued","processing","completed","failed"],"type":"string"}},"type":"object"},"QueryAnswer":{"description":"The answer to one query.","properties":{"answer":{"description":"A string, or an object following the query's `schema`."},"citations":{"description":"Every page and quote the answer came from.","items":{"properties":{"page":{"type":"integer"},"quote":{"type":"string"}},"type":"object"},"type":"array"},"confidence":{"description":"How sure the model is, from 0 to 1.","maximum":1,"minimum":0,"type":"number"},"not_found":{"description":"`true` when the document does not answer the question.","type":"boolean"}},"type":"object"},"UsageRecord":{"properties":{"amount_micro":{"type":"integer"},"created_at":{"format":"date-time","type":"string"},"document_id":{"type":"string"},"id":{"type":"string"},"model":{"type":"string"},"quantity":{"type":"integer"},"query_id":{"type":"string"},"sku":{"type":"string"},"stage":{"enum":["analysis","extraction","query","embedding"],"type":"string"},"unit_divisor":{"description":"1 for pages, 1000000 for tokens","type":"integer"},"unit_price_micro":{"type":"integer"}},"type":"object"}},"securitySchemes":{"bearerAuth":{"description":"`Authorization: Bearer ak_live_…` (or `ak_test_…` to run against the free fakes)","scheme":"bearer","type":"http"}}},"info":{"description":"Turn PDFs, scans and Office files into text, pictures and vectors, and\nlayer AI on top when you want it. Submit a document and poll until it is\n`completed`. By default you get every page's text, tables and key/value\npairs, and pictures of its charts, scans, stamps and signatures: no AI\nmodel runs. Ask for `embeddings`, built-in `extraction.fields` (summary,\nparties, dates and more), your own `extraction.schema` or `queries`, and\nthe model reads the text and pictures together and cites the page and the\nwords behind every value. Every request is authenticated with an API key and rate\nlimited per second by your plan (`X-RateLimit-*` headers). Work is priced\nper page and per token in micro-USD (1e-6 USD) and charged to your credit\nbalance; `ak_test_…` keys run against deterministic fakes and are free.\n","title":"Northdoc API","version":"1.0.0"},"openapi":"3.1.0","paths":{"/account":{"get":{"description":"Rate limited but not charged, so you can poll it. Read `credits.available_micro`\nbefore a big batch, and `limits` to size uploads: exceeding\n`max_upload_bytes` is a 413 and exceeding `max_pages_per_document` a 422.\n","operationId":"getAccount","responses":{"200":{"content":{"application/json":{"example":{"credits":{"available_micro":25000000},"key":{"id":"33e8…","mode":"live","name":"Production backend","prefix":"ak_live_go5cek5F…"},"limits":{"max_concurrent_jobs":5,"max_pages_per_document":1000,"max_retention_seconds":0,"max_upload_bytes":200000000},"organization":{"id":"961b…","name":"Acme Robotics","slug":"acme-robotics"},"plan":{"id":"payg","name":"Pay as you go"},"rate_limit_per_second":10},"schema":{"$ref":"#/components/schemas/Account"}}},"description":"The workspace, its plan, credit and limits."},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"Workspace, plan, credits and limits","tags":["Account"],"x-examples":[{"description":"Amounts are micro-USD (1e-6 USD), so 25000000 is $25.00. Divide by\n1000000 for dollars.\n","name":"Check credit before a batch","request":"curl \"$NORTHDOC_API/account\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"},{"description":"`max_retention_seconds` of `0` means the plan has no retention\nceiling, so `retention_seconds: 0` keeps results indefinitely.\n","name":"Size an upload against the plan","request":"curl -s \"$NORTHDOC_API/account\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  | jq '{credit_usd: (.credits.available_micro / 1000000), limits}'\n"}]}},"/documents":{"get":{"description":"Newest first. Page with `starting_after=<id>`; filter with `status`.","operationId":"listDocuments","parameters":[{"description":"How many to return.","example":"50","in":"query","name":"limit","schema":{"default":20,"maximum":100,"minimum":1,"type":"integer"}},{"description":"Id of the last document on the previous page; returns the ones after it.","example":"8f1c2d3e-…","in":"query","name":"starting_after","schema":{"type":"string"}},{"description":"Only documents in this state.","example":"completed","in":"query","name":"status","schema":{"enum":["queued","processing","completed","failed","expired"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"filename":"inv-1042.pdf","id":"8f1c…","object":"document","page_count":2,"status":"completed"}],"has_more":false,"object":"list"},"schema":{"properties":{"data":{"description":"Documents, newest first. `result` is left out of lists.","items":{"$ref":"#/components/schemas/Document"},"type":"array"},"has_more":{"description":"`true` when there are more: pass the last id as `starting_after`.","type":"boolean"},"object":{"description":"Always `list`.","type":"string"}},"type":"object"}}},"description":"A page of documents."},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"422":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"List documents","tags":["Documents"],"x-examples":[{"name":"Most recent documents","request":"curl \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"},{"description":"Handy for a retry sweep; pair with `error.type` on each document.","name":"Only the ones that failed","request":"curl \"$NORTHDOC_API/documents?status=failed&limit=100\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"},{"description":"Take the `id` of the last item, pass it as `starting_after`, and stop\nwhen `has_more` is `false`.\n","name":"Page through everything","request":"curl \"$NORTHDOC_API/documents?limit=100&starting_after=8f1c2d3e-…\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"}]},"post":{"description":"Send `multipart/form-data` with `file` (or several `files[]`) and an\noptional `options` field containing a JSON `DocumentOptions` object, or\na JSON body with a `url` to fetch. Poll `poll_url` until `status` is\n`completed` or `failed`.\n\nWith no options the document is read (text, tables, key/value pairs and\nlayout for every page) and its figures and picture-heavy pages are\nturned into images. That is all: no AI model runs, `result` is `null`,\nand you pay for the pages. Everything else is opt-in:\n`embeddings` makes vectors, `extraction` has the model fill\n`result.data` (built-in `fields` and/or your own `schema`), and\n`queries` has it answer questions.\n","operationId":"createDocument","requestBody":{"content":{"application/json":{"example":{"options":{"embeddings":true,"extraction":{"fields":["summary","dates"],"schema":{"properties":{"invoice_number":{"type":"string"},"total":{"type":"number"}},"type":"object"}},"queries":["What is the total amount due?"],"retention_seconds":3600},"url":"https://files.example.com/invoices/inv-1042.pdf"},"schema":{"properties":{"options":{"$ref":"#/components/schemas/DocumentOptions","description":"Processing options, as a JSON object. Every option is optional."},"url":{"description":"http(s) URL of a PDF, image or Office file. Pre-signed object-storage links are fine.","format":"uri","maxLength":8192,"type":"string"}},"required":["url"],"type":"object"}},"multipart/form-data":{"schema":{"properties":{"file":{"description":"The document: a PDF, image or Office file. Send `file` or `files[]`.","format":"binary","type":"string"},"files":{"description":"Up to 10 documents at once, as repeated `files[]` parts. Each becomes its own document.","items":{"format":"binary","type":"string"},"type":"array"},"options":{"description":"Processing options, as a JSON **string** in its own form part. Every option is optional.","type":"string","x-json-schema":{"$ref":"#/components/schemas/DocumentOptions"}}},"type":"object"}}},"required":true},"responses":{"202":{"content":{"application/json":{"examples":{"batch":{"summary":"Several files, one rejected","value":{"documents":[{"estimated_cost_micro":60000,"id":"8f1c…","object":"document","poll_url":"https://northdoc.northcape.tech/api/v1/documents/8f1c…","status":"queued"},{"estimated_cost_micro":30000,"id":"9a2d…","object":"document","poll_url":"https://northdoc.northcape.tech/api/v1/documents/9a2d…","status":"queued"},{"error":{"message":"Unsupported file type.","type":"unsupported_media_type"}}]}},"single":{"summary":"One file or URL","value":{"estimated_cost_micro":60000,"id":"8f1c…","object":"document","poll_url":"https://northdoc.northcape.tech/api/v1/documents/8f1c…","status":"queued"}}},"schema":{"$ref":"#/components/schemas/Accepted"}}},"description":"Accepted for processing. A single file or `url` returns the document\nitself; a batch returns `{\"documents\": [...]}` with one entry per\nfile, in order. Batch entries are independent — a file that is\nrejected comes back as `{\"error\": {...}}` in its slot while the\nothers are still accepted, so check each one.\n"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/InsufficientCredits"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"Submit a document","tags":["Documents"],"x-cost":"$0.025/page (layout) or $0.004/page (read), + tokens for what you switch on","x-examples":[{"description":"The smallest request, and the leanest: the pages are read and the\npictures taken, and nothing else. No AI model runs, so you pay only\nfor the pages, and the finished document's `result` is `null`. Read\nthe text from `GET /documents/{id}/pages` and the pictures from\n`GET /documents/{id}/images`.\n","name":"Upload a file","request":"curl -X POST \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -F file=@invoice.pdf\n","response":"{\n  \"id\": \"8f1c2d3e-…\",\n  \"object\": \"document\",\n  \"status\": \"queued\",\n  \"estimated_cost_micro\": 90000,\n  \"poll_url\": \"https://northdoc.northcape.tech/api/v1/documents/8f1c2d3e-…\"\n}\n"},{"description":"The same, plus a vector per page for your own search or model.\nStill no AI reading the document: you pay for the pages and the\nvectors (`compass.input`). Then fetch every page with its text,\nvector and pictures in one call:\n`GET /documents/{id}/pages?include=embeddings,image_data`.\n","name":"Text, pictures and vectors","request":"curl -X POST \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -F file=@site-report.pdf \\\n  -F 'options={\"embeddings\": true}'\n"},{"description":"`extraction.fields` picks from Northdoc's built-in fields: `title`,\n`document_type`, `summary`, `dates`, `parties`, `amounts` and\n`key_facts`. Only the ones you name come back in `result.data`, each\ncited in `result.citations`.\n","name":"A summary, the parties and the dates","request":"curl -X POST \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -F file=@contract.pdf \\\n  -F 'options={\"extraction\": {\"fields\": [\"summary\", \"parties\", \"dates\"]}}'\n","response":"{\n  \"status\": \"completed\",\n  \"result\": {\n    \"data\": {\n      \"summary\": \"A one-year services agreement between Acme Robotics and Jane Doe, renewing automatically unless either side gives 30 days' notice.\",\n      \"parties\": [{\"name\": \"Acme Robotics\", \"role\": \"supplier\"}, {\"name\": \"Jane Doe\", \"role\": \"customer\"}],\n      \"dates\": [{\"label\": \"Start date\", \"date\": \"2026-07-01\"}]\n    },\n    \"citations\": [\n      {\"path\": \"data.parties[0].name\", \"page\": 1, \"quote\": \"between Acme Robotics and Jane Doe\", \"confidence\": 0.97},\n      {\"path\": \"data.dates[0].date\", \"page\": 1, \"quote\": \"commencing 1 July 2026\", \"confidence\": 0.94}\n    ]\n  }\n}\n"},{"description":"`extraction.schema` is a JSON Schema (`type: object`) that\n`result.data` must follow. Every leaf you define comes back in\n`result.data`, with a page and a supporting quote in\n`result.citations`. Add `extraction.instructions` to steer\nambiguous fields. You can name built-in `fields` alongside it; they\nland in the same `result.data`.\n","name":"Extract to your own schema","request":"curl -X POST \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -F file=@invoice.pdf \\\n  -F 'options={\n        \"extraction\": {\n          \"schema\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"invoice_number\": {\"type\": \"string\"},\n              \"total\":          {\"type\": \"number\"},\n              \"due_date\":       {\"type\": \"string\", \"format\": \"date\"}\n            },\n            \"required\": [\"invoice_number\", \"total\"]\n          },\n          \"instructions\": \"total is the amount payable after tax and credits.\"\n        }\n      }'\n","response":"{\n  \"status\": \"completed\",\n  \"result\": {\n    \"data\": {\"invoice_number\": \"INV-1042\", \"total\": 1234.0, \"due_date\": \"2026-10-01\"},\n    \"citations\": [\n      {\"path\": \"data.total\", \"page\": 2, \"quote\": \"Total amount due $1,234.00\", \"confidence\": 0.95}\n    ]\n  }\n}\n"},{"description":"`queries` are answered while the document is processed and land in\n`result.answers`, in the order you sent them. Cheaper than one\n`POST /documents/{id}/queries` per question when you already know\nwhat to ask. Use the queries endpoint for follow-ups you discover\nlater; you can ask those of any document, AI options or not.\n","name":"Ask questions during ingest","request":"curl -X POST \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -F file=@contract.pdf \\\n  -F 'options={\"queries\":[\"Who are the parties?\",\"What is the termination notice period?\"]}'\n","response":"{\n  \"status\": \"completed\",\n  \"result\": {\n    \"answers\": [\n      {\"question\": \"Who are the parties?\", \"answer\": \"Acme Robotics and Jane Doe\", \"page\": 1, \"quote\": \"between Acme Robotics and Jane Doe\", \"not_found\": false},\n      {\"question\": \"What is the termination notice period?\", \"answer\": \"30 days\", \"page\": 4, \"quote\": \"upon thirty (30) days written notice\", \"not_found\": false}\n    ]\n  }\n}\n"},{"description":"`\"embeddings\": true` makes one 1,024-number vector per page. An\nobject picks the settings instead: `dimensions` 1024, 512 or 256,\nand `granularity`. Read the vectors back from\n`GET /documents/{id}/pages?include=embeddings`;\n`GET /documents/{id}` does not carry them. Billed as\n`compass.input`.\n","name":"Choose the vector settings","request":"curl -X POST \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -F file=@handbook.pdf \\\n  -F 'options={\"embeddings\": {\"granularity\": \"page\", \"dimensions\": 512}}'\n"},{"description":"The JSON form takes `options` as a real object, not a string. The URL\nmust be reachable without credentials; a 404 fails the document at\nthe `fetching` stage.\n","name":"Fetch from a URL (JSON body)","request":"curl -X POST \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n        \"url\": \"https://files.example.com/invoices/inv-1042.pdf\",\n        \"options\": {\"embeddings\": true, \"retention_seconds\": 3600}\n      }'\n"},{"description":"Repeat the `files[]` part, up to 10 per request. Each file becomes\nits own document, charged separately, and the response is\n`{\"documents\": [...]}` in the order you sent them.\n\nMind the brackets: `-F files=@a -F files=@b` (without `[]`) is\ncollapsed to a single upload before it reaches the API, so you get\none document instead of two.\n","name":"Several files at once","request":"curl -X POST \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -F \"files[]=@jan.pdf\" \\\n  -F \"files[]=@feb.pdf\" \\\n  -F \"files[]=@mar.pdf\"\n"},{"description":"The pictures are taken for every document, so when the model runs\nit reads them too: figures are placed where they sit in the text,\nand scanned and picture-heavy pages go in whole. Ask about what only\na picture shows and the answer cites the page, with the figure's\ncaption (or a short description of where it is) as the `quote`.\n","name":"Ask about charts, scans and signatures","request":"curl -X POST \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -F file=@annual-report.pdf \\\n  -F 'options={\"queries\":[\"What was revenue in Q3, according to the chart?\",\"Is page 12 signed?\"]}'\n","response":"{\n  \"status\": \"completed\",\n  \"result\": {\n    \"answers\": [\n      {\"question\": \"What was revenue in Q3, according to the chart?\", \"answer\": \"$4.2 million\", \"page\": 3, \"quote\": \"Figure (page 3): Quarterly revenue, FY2026\", \"not_found\": false},\n      {\"question\": \"Is page 12 signed?\", \"answer\": \"Yes, by the chair, dated 14 August 2026\", \"page\": 12, \"quote\": \"Signed by the chair above the signature line\", \"not_found\": false}\n    ]\n  }\n}\n"},{"description":"`images: false` takes no pictures: `GET /documents/{id}/images` is\nempty, and if the model runs it reads the text alone, which costs\nfewer tokens but leaves charts, stamps and signatures invisible.\n","name":"No pictures","request":"curl -X POST \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -F file=@typed-letter.pdf \\\n  -F 'options={\"images\": false}'\n"},{"description":"`analysis: read` is OCR without layout analysis, roughly six times\ncheaper per page ($0.004 vs $0.025). Pages come back without tables,\nkey/value pairs or figures, and `markdown: true` alongside it is a\n422.\n","name":"Cheap OCR only","request":"curl -X POST \"$NORTHDOC_API/documents\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -F file=@scan.pdf \\\n  -F 'options={\"analysis\":\"read\"}'\n"}]}},"/documents/{id}":{"delete":{"description":"Purges the payload and removes the document. Usage records are kept.\nWhile a question about the document is still being answered the\ndelete is refused with `409 conflict`; try again a moment later.\n","operationId":"deleteDocument","parameters":[{"description":"The document's id.","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"content":{"application/json":{"example":{"error":{"message":"A query on this document is still running. Try again in a moment.","type":"conflict"}}}},"description":"A query on this document is still running"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"Delete a document","tags":["Documents"],"x-examples":[{"description":"Purges the file, its text and its results immediately, ahead of the\nretention clock. Usage records survive, so your billing history and\n`GET /usage` are unaffected.\n","name":"Delete a document","request":"curl -X DELETE \"$NORTHDOC_API/documents/$DOC_ID\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -i\n"}]},"get":{"description":"Poll this until `status` is `completed` or `failed`. `result` appears\nonce completed, `error` once failed.\n\nBy default the response is metadata plus `result`, which is `null`\nunless the document was sent with an `extraction` or `queries`. The\nbulky parts are opt-in through `include`, and it only shows data that\nwas produced: `markdown` exists only for a document sent with\n`markdown: true`, and `tables` and `key_values` only with\n`analysis: layout` (the default).\nEmbeddings are the one extra that is **not** available here; read them\nfrom `GET /documents/{id}/pages?include=embeddings`.\n\nThe first read of a completed document sets `retrieved_at`. A result\nnobody has fetched is kept at least 24 hours after it completes,\nhowever short its `retention_seconds`.\n","operationId":"getDocument","parameters":[{"description":"The document id from the submit response.","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Comma-separated extras to embed in the response:\n`text` (the stitched plain text sent to the model),\n`markdown` (needs `markdown: true` on the document),\n`pages` (the per-page array),\n`tables` and `key_values` (added to each page, so pair them with `pages`),\n`usage` (priced records for this document),\n`options` (the options the document was submitted with).\n","example":"text,pages,usage","in":"query","name":"include","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"analysis":"layout","completed_at":"2026-09-10T12:00:05Z","content_type":"application/pdf","cost":{"estimated_micro":110843,"settled_micro":61250},"expires_at":"2026-09-10T13:00:05Z","filename":"inv-1042.pdf","id":"8f1c…","mode":"live","model":{"requested":"auto","used":"northdoc-swift-1"},"object":"document","page_count":2,"result":{"answers":[{"answer":"$1,234.00","not_found":false,"page":2,"question":"What is the total amount due?","quote":"Total amount due $1,234.00"}],"citations":[{"confidence":0.95,"page":2,"path":"data.total","quote":"Total amount due $1,234.00"}],"data":{"invoice_number":"INV-1042","total":1234.0}},"retrieved_at":null,"stage":"done","status":"completed"},"schema":{"$ref":"#/components/schemas/Document"}}},"description":"The document (`result` is present once completed; `error` once failed)"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"410":{"$ref":"#/components/responses/DocumentExpired"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"Get a document and its result","tags":["Documents"],"x-examples":[{"description":"Polling spends no credits, but each call counts towards your rate\nlimit (and, on the free trial, its monthly request quota), so poll\nevery second or two rather than in a tight loop. `stage` tells\nyou where it is: `fetching`, `analyzing`, `rendering`, `reserving`,\n`extracting`, `embedding`, `finalizing`, then `done`.\n","name":"Poll until it is done","request":"curl \"$NORTHDOC_API/documents/$DOC_ID\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n","response":"{\n  \"id\": \"8f1c2d3e-…\",\n  \"status\": \"processing\",\n  \"stage\": \"extracting\",\n  \"page_count\": 2,\n  \"cost\": {\"estimated_micro\": 110843, \"settled_micro\": null}\n}\n"},{"description":"For a document sent with an `extraction`, `result.data` is there once\nit completes, so the bare request is all you need.\n","name":"Just the extracted data","request":"curl \"$NORTHDOC_API/documents/$DOC_ID\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  | jq .result.data\n"},{"name":"Full text","request":"curl \"$NORTHDOC_API/documents/$DOC_ID?include=text\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"},{"description":"`tables` and `key_values` attach to each page, so include `pages`\ntoo. They come from `analysis: layout`, the default.\n","name":"Pages with tables and key/values","request":"curl \"$NORTHDOC_API/documents/$DOC_ID?include=pages,tables,key_values\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"},{"description":"`usage` breaks the charge down per SKU; `options` echoes back the\noptions the document was created with, which is useful when you are\nreproducing someone else's result.\n","name":"What it cost, and how it was configured","request":"curl \"$NORTHDOC_API/documents/$DOC_ID?include=usage,options\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n","response":"{\n  \"usage\": {\n    \"amount_micro\": 61250,\n    \"by_sku\": {\"pages.layout\": {\"quantity\": 2, \"amount_micro\": 50000}, \"swift.input\": {\"quantity\": 3200, \"amount_micro\": 8800}, \"swift.output\": {\"quantity\": 178, \"amount_micro\": 2450}},\n    \"records\": [\n      {\"stage\": \"analysis\", \"sku\": \"pages.layout\", \"quantity\": 2, \"amount_micro\": 50000}\n    ]\n  },\n  \"options\": {\"images\": true, \"embeddings\": null, \"markdown\": false, \"extraction\": {\"fields\": [\"summary\"]}, \"retention_seconds\": 86400}\n}\n"}]}},"/documents/{id}/images":{"get":{"description":"The pictures Northdoc took from the document (every document, unless it\nwas sent with `images: false`): figures cropped from their pages, and whole pages that are\nmostly picture or have fewer than 25 words, such as scans and signed\npages. Logos, tiny figures and blank pages are left out.\n\nThis lists them, in page order, with their metadata and a `url`; fetch\neach `url` for the PNG (figures) or JPEG (pages) itself. The first\n`[FIGURE]` marker in a page's text is the image with that `page` and\n`figure_index: 0`, the second is `figure_index: 1`, and so on.\n","operationId":"listDocumentImages","parameters":[{"description":"The document's id.","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"One page (`3`) or an inclusive range (`1-3`).","example":"2-4","in":"query","name":"page","schema":{"type":"string"}},{"description":"`data` adds each image's bytes as base64 `data`, so the list is the pictures themselves (at most 25 MB of them; narrow with `page` or download each from its `url`).","example":"data","in":"query","name":"include","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"bbox":{"height":0.41,"left":0.12,"top":0.38,"width":0.76},"byte_size":412880,"caption":"Photo 2: Cracking to the north wall","figure_index":0,"height":930,"id":"5c1e…","kind":"figure","media_type":"image/png","object":"image","page":3,"url":"https://northdoc.northcape.tech/api/v1/documents/8f1c…/images/5c1e…","width":1240}],"document_id":"8f1c…","object":"list"},"schema":{"properties":{"data":{"description":"In page order, figures in their order on the page.","items":{"$ref":"#/components/schemas/Image"},"type":"array"},"document_id":{"description":"The document these belong to.","type":"string"},"object":{"description":"Always `list`.","type":"string"}},"type":"object"}}},"description":"The document's pictures."},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DocumentNotReady"},"410":{"$ref":"#/components/responses/DocumentExpired"},"422":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"Pictures of a completed document","tags":["Documents"],"x-examples":[{"description":"Works whether or not the model ran: the pictures are taken for every\ndocument, AI options or not.\n","name":"Every picture in a document","request":"curl \"$NORTHDOC_API/documents/$DOC_ID/images\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n","response":"{\n  \"object\": \"list\",\n  \"document_id\": \"8f1c2d3e-…\",\n  \"data\": [\n    {\"id\": \"5c1e…\", \"object\": \"image\", \"page\": 3, \"kind\": \"figure\", \"figure_index\": 0,\n     \"caption\": \"Photo 2: Cracking to the north wall\", \"media_type\": \"image/png\",\n     \"width\": 1240, \"height\": 930, \"byte_size\": 412880,\n     \"bbox\": {\"left\": 0.12, \"top\": 0.38, \"width\": 0.76, \"height\": 0.41},\n     \"url\": \"https://northdoc.northcape.tech/api/v1/documents/8f1c2d3e-…/images/5c1e…\"},\n    {\"id\": \"7a90…\", \"object\": \"image\", \"page\": 12, \"kind\": \"page\", \"figure_index\": null,\n     \"caption\": null, \"media_type\": \"image/jpeg\",\n     \"width\": 1109, \"height\": 1568, \"byte_size\": 286411, \"bbox\": null,\n     \"url\": \"https://northdoc.northcape.tech/api/v1/documents/8f1c2d3e-…/images/7a90…\"}\n  ]\n}\n"},{"name":"Pictures from some pages","request":"curl \"$NORTHDOC_API/documents/$DOC_ID/images?page=2-4\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"}]}},"/documents/{id}/images/{image_id}":{"get":{"description":"The image file itself: `image/png` for a cropped figure, `image/jpeg`\nfor a whole page, at most 1568px on the long side. Use the `url` from\nthe images list rather than building it.\n","operationId":"getDocumentImage","parameters":[{"description":"The document's id.","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"The image's id, from the images list.","in":"path","name":"image_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The image bytes (`image/png` or `image/jpeg`)"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DocumentNotReady"},"410":{"$ref":"#/components/responses/DocumentExpired"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"Download one picture","tags":["Documents"],"x-examples":[{"name":"Save a picture to a file","request":"curl -o page-3-figure-0.png \"$NORTHDOC_API/documents/$DOC_ID/images/5c1e…\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"}]}},"/documents/{id}/pages":{"get":{"description":"Per-page text, word count and (with `extraction.per_page`) the per-page\nextraction result.\n\nThis is the **only** endpoint that returns embedding vectors. Each\nextra is opt-in through `include`. Vectors exist only for a document\nsent with `embeddings`; tables and key/value pairs only with\n`analysis: layout` (the default), so a `read` document returns them\nempty.\n","operationId":"listDocumentPages","parameters":[{"description":"The document's id.","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Comma-separated extras per page:\n`embeddings` (the vector, its model and dimensions; needs\n`embeddings` on the document),\n`tables` and `key_values` (from `analysis: layout`, the default),\n`layout` (raw layout elements with their bounding boxes),\n`images` (the page's pictures, each with a download `url`),\n`image_data` (the same pictures with their bytes as base64 `data`;\nat most 25 MB of pictures a response, so narrow it with `page` for a\npicture-heavy document, or download each from its `url`).\n","example":"tables,key_values","in":"query","name":"include","schema":{"type":"string"}},{"description":"One page (`3`) or an inclusive range (`1-3`). Anything else is a 422.","example":"1-3","in":"query","name":"page","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"key_values":{"Invoice number":{"key_confidence":93.0,"selection_status":null,"value":"INV-1042","value_confidence":91.0}},"page":1,"tables":[{"columns":2,"markdown":"| Item | Amount |\n| - | - |\n| Widget | $10.00 |","rows":2}],"text":"# Invoice\n\nWidget $10.00","word_count":4}],"document_id":"8f1c…","object":"list"},"schema":{"properties":{"data":{"description":"One per page, in page order.","items":{"$ref":"#/components/schemas/DocumentPage"},"type":"array"},"document_id":{"description":"The document these belong to.","type":"string"},"object":{"description":"Always `list`.","type":"string"}},"type":"object"}}},"description":"The document's pages."},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DocumentNotReady"},"410":{"$ref":"#/components/responses/DocumentExpired"},"422":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"Pages of a completed document","tags":["Documents"],"x-examples":[{"name":"Every page","request":"curl \"$NORTHDOC_API/documents/$DOC_ID/pages\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n","response":"{\n  \"object\": \"list\",\n  \"document_id\": \"8f1c2d3e-…\",\n  \"data\": [\n    {\"page\": 1, \"text\": \"# Invoice\\n\\nWidget $10.00\", \"word_count\": 4, \"result\": null}\n  ]\n}\n"},{"description":"Useful for long documents where you only care about a section.","name":"A range of pages","request":"curl \"$NORTHDOC_API/documents/$DOC_ID/pages?page=1-3\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"},{"description":"Requires the document to have been submitted with `embeddings`.\nEach page carries an `embedding` object; the vector\nlength matches the `dimensions` you asked for (1024, 512 or 256).\n","name":"Embedding vectors","request":"curl \"$NORTHDOC_API/documents/$DOC_ID/pages?include=embeddings\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n","response":"{\n  \"object\": \"list\",\n  \"document_id\": \"8f1c2d3e-…\",\n  \"data\": [\n    {\n      \"page\": 1,\n      \"text\": \"# Invoice\\n\\nWidget $10.00\",\n      \"word_count\": 4,\n      \"embedding\": {\n        \"model\": \"northdoc-compass-1\",\n        \"dimensions\": 1024,\n        \"vector\": [0.0123, -0.0456, 0.0789, \"… 1021 more\"]\n      }\n    }\n  ]\n}\n"},{"description":"`tables` gives you each detected table as markdown plus its\ndimensions; `key_values` gives the labelled fields with the OCR\nconfidence for each. Both need `analysis: layout` (the default).\n","name":"Tables and key/value pairs","request":"curl \"$NORTHDOC_API/documents/$DOC_ID/pages?include=tables,key_values\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n","response":"{\n  \"data\": [\n    {\n      \"page\": 1,\n      \"key_values\": {\"Invoice number\": {\"value\": \"INV-1042\", \"key_confidence\": 93.0, \"value_confidence\": 91.0, \"selection_status\": null}},\n      \"tables\": [\n        {\"rows\": 2, \"columns\": 2, \"markdown\": \"| Item | Amount |\\n| - | - |\\n| Widget | $10.00 |\"}\n      ]\n    }\n  ]\n}\n"},{"description":"Every page with its text, its vector and its pictures, bytes\nincluded: decode each image's `data` from base64 to get the PNG or\nJPEG. Send the document with just `\"embeddings\": true` and this is\nyour own model's input, with no AI in between. Base64 makes the response about a\nthird bigger than the pictures, so fetch long documents a few pages\nat a time with `page`, or use `include=images` and download each\npicture from its `url`.\n","name":"Text, vectors and pictures in one call","request":"curl \"$NORTHDOC_API/documents/$DOC_ID/pages?include=embeddings,image_data\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n","response":"{\n  \"object\": \"list\",\n  \"document_id\": \"8f1c2d3e-…\",\n  \"data\": [\n    {\n      \"page\": 3,\n      \"text\": \"## Exterior\\n\\nCracking is visible along the north wall.\\n\\n[FIGURE]\\n\\nThe crack runs from the window head to the slab.\",\n      \"word_count\": 214,\n      \"result\": null,\n      \"embedding\": {\"model\": \"northdoc-compass-1\", \"dimensions\": 1024, \"vector\": [0.0123, -0.0456, \"… 1022 more\"]},\n      \"images\": [\n        {\"id\": \"5c1e…\", \"object\": \"image\", \"page\": 3, \"kind\": \"figure\", \"figure_index\": 0,\n         \"caption\": \"Photo 2: Cracking to the north wall\", \"media_type\": \"image/png\",\n         \"width\": 1240, \"height\": 930, \"byte_size\": 412880,\n         \"bbox\": {\"left\": 0.12, \"top\": 0.38, \"width\": 0.76, \"height\": 0.41},\n         \"url\": \"https://northdoc.northcape.tech/api/v1/documents/8f1c2d3e-…/images/5c1e…\",\n         \"data\": \"iVBORw0KGgoAAAANSUhEUgAABNgAAAOi…\"}\n      ]\n    }\n  ]\n}\n"},{"name":"One page, everything about it","request":"curl \"$NORTHDOC_API/documents/$DOC_ID/pages?page=2&include=tables,key_values,layout,embeddings,image_data\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"}]}},"/documents/{id}/queries":{"get":{"description":"Newest first. Every question ever asked of this document, with its answer.","operationId":"listQueries","parameters":[{"description":"The document's id.","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"How many to return.","example":"50","in":"query","name":"limit","schema":{"default":20,"maximum":100,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"example":{"data":[{"id":"c0de…","question":"Who are the parties?","status":"completed"}],"document_id":"8f1c…","object":"list"},"schema":{"properties":{"data":{"description":"Newest first, each with its answer.","items":{"$ref":"#/components/schemas/Query"},"type":"array"},"document_id":{"description":"The document these belong to.","type":"string"},"object":{"description":"Always `list`.","type":"string"}},"type":"object"}}},"description":"The document's questions."},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"List a document's queries","tags":["Queries"],"x-examples":[{"name":"Every question asked of a document","request":"curl \"$NORTHDOC_API/documents/$DOC_ID/queries\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"}]},"post":{"description":"Answers from the document's text and images with page citations. Give a JSON\n`schema` to get a structured `answer`. Runs synchronously and returns\n`200` when it finishes in time; send `\"async\": true` (or wait for a\n`202`) and poll the query instead. When the workspace already has\nseveral questions running it also answers `202`, and the question\nruns in the background. Repeated questions over the same document\nreuse a cached prompt prefix.\n\nA `200` can carry `status: \"failed\"` with an `error`: `type` is\n`insufficient_credits` (the credit left cannot cover this question's\nestimate), `document_too_large` (too long for the model you chose),\n`document_expired`, `schema_mismatch` or `query_failed`. A `402` means\nthe workspace has no credit left at all.\n","operationId":"createQuery","parameters":[{"description":"The document's id.","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"question":"Who are the parties to this agreement?"},"schema":{"properties":{"async":{"default":false,"description":"`true` answers `202` straight away with a `poll_url`, instead of waiting for the answer.","type":"boolean"},"instructions":{"description":"How to answer: length, units, what to do when unsure.","maxLength":4000,"type":"string"},"model":{"default":"auto","description":"Which model answers: `swift` (fast, economical), `summit` (most capable) or `auto` (by the document's size).","enum":["auto","swift","summit"],"type":"string"},"question":{"description":"What you want to know, in plain words.","maxLength":4000,"type":"string"},"schema":{"description":"A JSON Schema (`type: object`) the answer must follow. With one, `answer.answer` is an object you can store; without, it is a sentence.","type":"object"}},"required":["question"],"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"example":{"answer":{"answer":"Acme Robotics (vendor) and Jane Doe (purchaser).","citations":[{"page":1,"quote":"between Acme Robotics and Jane Doe"}],"confidence":0.92,"not_found":false},"cost":{"estimated_micro":2400,"settled_micro":1975},"document_id":"8f1c…","id":"c0de…","model":{"requested":"auto","used":"northdoc-swift-1"},"object":"query","question":"Who are the parties to this agreement?","status":"completed"},"schema":{"$ref":"#/components/schemas/Query"}}},"description":"Answered"},"202":{"content":{"application/json":{"example":{"document_id":"8f1c…","id":"c0de…","object":"query","poll_url":"https://northdoc.northcape.tech/api/v1/documents/8f1c…/queries/c0de…","status":"queued"},"schema":{"properties":{"document_id":{"description":"The document it was asked of.","type":"string"},"id":{"description":"The question's id.","type":"string"},"object":{"description":"Always `query`.","type":"string"},"poll_url":{"description":"Poll this until `status` is `completed` or `failed`.","type":"string"},"status":{"description":"Not answered yet.","enum":["queued","processing"],"type":"string"}},"type":"object"}}},"description":"Accepted; poll `poll_url`"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/InsufficientCredits"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DocumentNotReady"},"410":{"$ref":"#/components/responses/DocumentExpired"},"422":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"Ask a question","tags":["Queries"],"x-cost":"Model tokens (the document is cached after the first question)","x-examples":[{"description":"Returns `200` with the answer when it finishes in time. `citations`\npoint at the pages and quotes the answer came from; `not_found` is\n`true` when the document does not say.\n","name":"Ask a question","request":"curl -X POST \"$NORTHDOC_API/documents/$DOC_ID/queries\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"question\": \"Who are the parties to this agreement?\"}'\n","response":"{\n  \"id\": \"c0de1234-…\",\n  \"status\": \"completed\",\n  \"answer\": {\n    \"answer\": \"Acme Robotics (vendor) and Jane Doe (purchaser).\",\n    \"citations\": [{\"page\": 1, \"quote\": \"between Acme Robotics and Jane Doe\"}],\n    \"confidence\": 0.92,\n    \"not_found\": false\n  }\n}\n"},{"description":"Give a JSON Schema as `schema` and `answer.answer` becomes an object\nfollowing it instead of a string — the way to get machine-readable\nanswers without post-parsing prose.\n","name":"Get a structured answer","request":"curl -X POST \"$NORTHDOC_API/documents/$DOC_ID/queries\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n        \"question\": \"What are the payment terms?\",\n        \"schema\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"net_days\":       {\"type\": \"integer\"},\n            \"late_fee_pct\":   {\"type\": \"number\"},\n            \"currency\":       {\"type\": \"string\"}\n          },\n          \"required\": [\"net_days\"]\n        }\n      }'\n","response":"{\n  \"status\": \"completed\",\n  \"answer\": {\n    \"answer\": {\"net_days\": 30, \"late_fee_pct\": 1.5, \"currency\": \"USD\"},\n    \"citations\": [{\"page\": 3, \"quote\": \"Payment is due net 30 days\"}],\n    \"confidence\": 0.88,\n    \"not_found\": false\n  }\n}\n"},{"description":"`instructions` shape how to answer (tone, units, what to do when\nunsure). `model` overrides the automatic choice: `swift` is the\ncheap default up to ~150k tokens, `summit` handles up to ~900k\nand reasons better on dense legal or financial text.\n","name":"Steer the answer, pick the model","request":"curl -X POST \"$NORTHDOC_API/documents/$DOC_ID/queries\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n        \"question\": \"Summarise the indemnity obligations.\",\n        \"instructions\": \"Answer in at most three sentences. Quote clause numbers. Say so if the document is silent.\",\n        \"model\": \"summit\"\n      }'\n"},{"description":"Send `\"async\": true` to get a `202` with a `poll_url` immediately\ninstead of holding the connection. A slow synchronous query may\nreturn `202` on its own, so handle both statuses either way.\n","name":"Long question, answered in the background","request":"curl -X POST \"$NORTHDOC_API/documents/$DOC_ID/queries\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"question\": \"List every obligation with its deadline.\", \"async\": true}'\n","response":"{\n  \"id\": \"c0de1234-…\",\n  \"object\": \"query\",\n  \"document_id\": \"8f1c2d3e-…\",\n  \"status\": \"queued\",\n  \"poll_url\": \"https://northdoc.northcape.tech/api/v1/documents/8f1c2d3e-…/queries/c0de1234-…\"\n}\n"}]}},"/documents/{id}/queries/{query_id}":{"get":{"description":"Poll this after an async query, using the `poll_url` you were given.","operationId":"getQuery","parameters":[{"description":"The document's id.","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"The question's id.","in":"path","name":"query_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"answer":{"answer":"Acme Robotics and Jane Doe","citations":[{"page":1,"quote":"…"}],"confidence":0.9,"not_found":false},"id":"c0de…","object":"query","status":"completed"},"schema":{"$ref":"#/components/schemas/Query"}}},"description":"The question and, once completed, its answer."},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"Get a query","tags":["Queries"],"x-examples":[{"description":"Spends no credits, but costs one request unit per call like every\nother document endpoint. `status` moves `queued` → `processing` →\n`completed` (or `failed`, with `error`).\n","name":"Poll an async query","request":"curl \"$NORTHDOC_API/documents/$DOC_ID/queries/$QUERY_ID\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"}]}},"/me":{"get":{"description":"Rate limited but not metered. Use this for the monthly request quota\n(`usage.used` against `usage.limit`); prefer `/account` for credits and\ndocument limits.\n","operationId":"getMe","responses":{"200":{"content":{"application/json":{"example":{"key":{"id":"33e8…","mode":"live","name":"Production backend","prefix":"ak_live_go5cek5F…"},"organization":{"id":"961b…","name":"Acme Robotics","slug":"acme-robotics"},"plan":{"id":"free","name":"Free trial","rate_limit_per_second":2},"usage":{"included":10000,"limit":10000,"overage":0,"percent":0,"period_start":"2026-09-01T00:00:00Z","used":6}},"schema":{"properties":{"key":{"description":"The key that made the call. Only a prefix of it, never the secret.","properties":{"id":{"type":"string"},"mode":{"enum":["live","test"],"type":"string"},"name":{"type":"string"},"prefix":{"type":"string"}},"type":"object"},"organization":{"description":"The workspace the key belongs to.","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"type":"object"},"plan":{"description":"The workspace's plan.","properties":{"id":{"type":"string"},"name":{"type":"string"},"rate_limit_per_second":{"type":"integer"}},"type":"object"},"usage":{"description":"Requests this month against the plan's quota.","properties":{"included":{"type":"integer"},"limit":{"description":"`null` when there is no cap.","type":"integer"},"overage":{"type":"integer"},"percent":{"type":"integer"},"period_start":{"format":"date-time","type":"string"},"used":{"type":"integer"}},"type":"object"}},"type":"object"}}},"description":"Who the key belongs to, and the month's request quota."},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"Current key, workspace, plan and request quota","tags":["Account"],"x-examples":[{"description":"A good health check for a deployed integration: it proves the key\nworks and tells you which workspace and mode it belongs to.\n","name":"Who am I, and how much quota is left","request":"curl \"$NORTHDOC_API/me\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"}]}},"/usage":{"get":{"description":"Defaults to the last 30 days, grouped by SKU. Only the calling key's\nmode is included, so a test key never shows live spend and vice versa.\nAmounts are micro-USD; `quantity` (on rows grouped by `sku`) is pages\nfor `pages.*` SKUs and tokens for `swift.*`, `summit.*` and `compass.*`\nSKUs. Rows grouped by `day` carry `count` and `amount_micro` only.\n","operationId":"getUsage","parameters":[{"description":"Start of the period. An ISO 8601 datetime, or a plain `YYYY-MM-DD` date (treated as UTC midnight).","example":"2026-09-01","in":"query","name":"from","schema":{"type":"string"}},{"description":"End of the period, same formats, inclusive: a bare date covers the whole of that day. Defaults to now.","example":"2026-09-30","in":"query","name":"to","schema":{"type":"string"}},{"description":"`sku` to see what you are spending it on, `day` to see it over time.","example":"day","in":"query","name":"group_by","schema":{"default":"sku","enum":["sku","day"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"from":"2026-08-11T12:00:00Z","group_by":"sku","mode":"live","object":"usage","rows":[{"amount_micro":50000,"count":1,"key":"pages.layout","quantity":2},{"amount_micro":8800,"count":1,"key":"swift.input","quantity":3200},{"amount_micro":2450,"count":1,"key":"swift.output","quantity":178}],"to":"2026-09-10T12:00:00Z","total":{"amount_micro":61250}},"schema":{"properties":{"from":{"description":"Start of the period.","format":"date-time","type":"string"},"group_by":{"description":"How `rows` are grouped.","enum":["sku","day"],"type":"string"},"mode":{"description":"The calling key's mode; only its usage is counted.","enum":["live","test"],"type":"string"},"object":{"description":"Always `usage`.","type":"string"},"rows":{"description":"One per SKU or day.","items":{"properties":{"amount_micro":{"description":"Charged, in micro-USD.","type":"integer"},"count":{"description":"How many usage records.","type":"integer"},"key":{"description":"The SKU (like `pages.layout`) or the day (`YYYY-MM-DD`).","type":"string"},"quantity":{"description":"Pages for `pages.*` SKUs, tokens for the rest.","type":"integer"}},"type":"object"},"type":"array"},"to":{"description":"End of the period.","format":"date-time","type":"string"},"total":{"description":"The whole period.","properties":{"amount_micro":{"description":"Total charged, in micro-USD.","type":"integer"}},"type":"object"}},"type":"object"}}},"description":"Charges for the period, grouped."},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"}},"summary":"Priced usage for a period","tags":["Account"],"x-examples":[{"description":"The default. Shows which stage of the pipeline your money goes to.","name":"Last 30 days by SKU","request":"curl \"$NORTHDOC_API/usage\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"},{"name":"One calendar month","request":"curl \"$NORTHDOC_API/usage?from=2026-09-01&to=2026-09-30\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n"},{"name":"Daily spend, for a chart","request":"curl \"$NORTHDOC_API/usage?group_by=day&from=2026-09-01\" \\\n  -H \"Authorization: Bearer $NORTHDOC_KEY\"\n","response":"{\n  \"object\": \"usage\",\n  \"group_by\": \"day\",\n  \"total\": {\"amount_micro\": 184300},\n  \"rows\": [\n    {\"key\": \"2026-09-01\", \"amount_micro\": 61250, \"count\": 4},\n    {\"key\": \"2026-09-02\", \"amount_micro\": 123050, \"count\": 7}\n  ]\n}\n"}]}}},"security":[{"bearerAuth":[]}],"servers":[{"url":"/api/v1"}],"tags":[{"description":"Submit documents and read their extracted results.","name":"Documents"},{"description":"Ask questions of a completed document.","name":"Queries"},{"description":"Who you are, what you may do, and what you have spent.","name":"Account"}]}