@talonic/docs 0.19.3 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/content.js CHANGED
@@ -34,7 +34,9 @@ var API_NAV_SECTIONS = [
34
34
  { id: "introduction", label: "Introduction" },
35
35
  { id: "authentication", label: "Authentication" },
36
36
  { id: "base-url", label: "Base URL" },
37
- { id: "quick-start", label: "Quick Start" }
37
+ { id: "quick-start", label: "Quick Start" },
38
+ { id: "pagination", label: "Pagination" },
39
+ { id: "idempotency", label: "Idempotency" }
38
40
  ] },
39
41
  { id: "extract", label: "Extract", children: [
40
42
  { id: "post-extract", label: "POST /v1/extract" },
@@ -4426,11 +4428,23 @@ var sections17 = [
4426
4428
  parentSlug: "overview",
4427
4429
  title: "Authentication",
4428
4430
  seoTitle: "API Authentication \u2014 Talonic Docs",
4429
- description: "Learn how to authenticate with the Talonic API using Bearer tokens and API keys with the tlnc_ prefix, scoped to a source.",
4431
+ description: "Learn how to authenticate with the Talonic API using Bearer tokens and API keys with the tlnc_ prefix. Keys carry scopes (extract, read, write) that control access.",
4430
4432
  content: [
4431
- { type: "paragraph", text: "All API requests require a Bearer token in the `Authorization` header. API keys are scoped to a source and carry the `tlnc_` prefix. You can create and manage keys from **Settings → API Keys** in the dashboard." },
4433
+ { type: "paragraph", text: "All API requests require a Bearer token in the `Authorization` header. API keys carry the `tlnc_` prefix and can be scoped to a source. Create and manage keys from **Settings \u2192 API Keys** in the dashboard." },
4432
4434
  { type: "code", language: "bash", title: "Authorization header", code: `curl https://api.talonic.com/v1/documents \\
4433
- -H "Authorization: Bearer tlnc_sk_live_7f3a...x9k2"` },
4435
+ -H "Authorization: Bearer $TALONIC_API_KEY"` },
4436
+ { type: "heading", level: 2, id: "api-key-scopes", text: "API Key Scopes" },
4437
+ { type: "paragraph", text: "Each API key carries one or more scopes that determine which operations it can perform. New keys default to all three scopes." },
4438
+ {
4439
+ type: "param-table",
4440
+ title: "Available scopes",
4441
+ params: [
4442
+ { name: "extract", type: "scope", description: "Submit documents for extraction (`POST /v1/extract`, `POST /v1/documents/:id/re-extract`)." },
4443
+ { name: "read", type: "scope", description: "Read operations \u2014 list and retrieve documents, extractions, schemas, jobs, sources, and other resources." },
4444
+ { name: "write", type: "scope", description: "Write operations \u2014 create, update, and delete schemas, sources, jobs, delivery bindings, and other resources." }
4445
+ ]
4446
+ },
4447
+ { type: "paragraph", text: "If a request requires a scope your key does not carry, the API returns `403` with error code `insufficient_scope` and lists the required scopes in the response body." },
4434
4448
  { type: "callout", text: "Keep your API key secret. Do not expose it in client-side code or version control. If a key is compromised, revoke it immediately from the dashboard." }
4435
4449
  ],
4436
4450
  related: [
@@ -4438,10 +4452,11 @@ var sections17 = [
4438
4452
  { label: "Error Codes", slug: "error-codes" }
4439
4453
  ],
4440
4454
  faq: [
4441
- { question: "How do I authenticate with the Talonic API?", answer: "Include a Bearer token in the Authorization header of every request. API keys use the tlnc_ prefix and are scoped to a source." },
4442
- { question: "Where do I get an API key?", answer: "Create and manage API keys from Settings > API Keys in the Talonic dashboard." }
4455
+ { question: "How do I authenticate with the Talonic API?", answer: "Include a Bearer token in the Authorization header of every request. API keys use the tlnc_ prefix." },
4456
+ { question: "Where do I get an API key?", answer: "Create and manage API keys from Settings \u2192 API Keys in the Talonic dashboard." },
4457
+ { question: "What scopes are available?", answer: "Three scopes: extract (submit documents), read (list/retrieve resources), and write (create/update/delete resources). New keys get all three by default." }
4443
4458
  ],
4444
- mentions: ["Bearer token", "API key", "Authorization header"]
4459
+ mentions: ["Bearer token", "API key", "Authorization header", "scopes", "extract", "read", "write"]
4445
4460
  },
4446
4461
  {
4447
4462
  slug: "base-url",
@@ -4466,55 +4481,226 @@ var sections17 = [
4466
4481
  parentSlug: "overview",
4467
4482
  title: "Quick Start",
4468
4483
  seoTitle: "API Quick Start Guide \u2014 Talonic Docs",
4469
- description: "Get started with the Talonic API in three steps: extract a document with an inline schema, save the schema, and query extraction results.",
4484
+ description: "Get started with the Talonic API in under 60 seconds. Extract structured data from a document with a single curl command using sync mode.",
4470
4485
  content: [
4471
- { type: "paragraph", text: "Extract structured data from a document in three steps." },
4472
- { type: "heading", level: 3, id: "step-1", text: "1. Extract a document with an inline schema" },
4473
- { type: "code", language: "bash", title: "Step 1 \u2014 Extract", code: `curl -X POST https://api.talonic.com/v1/extract \\
4474
- -H "Authorization: Bearer tlnc_sk_live_7f3a...x9k2" \\
4486
+ { type: "paragraph", text: "Extract structured data from a document in a single API call. This guide uses **sync mode** (documents \u22645 pages return results immediately)." },
4487
+ { type: "heading", level: 3, id: "prerequisites", text: "Prerequisites" },
4488
+ { type: "list", items: [
4489
+ "A Talonic account \u2014 sign up at [app.talonic.com](https://app.talonic.com)",
4490
+ "An API key from **Settings \u2192 API Keys** (starts with `tlnc_`)",
4491
+ "A PDF or image file to extract (e.g. an invoice)"
4492
+ ] },
4493
+ { type: "code", language: "bash", title: "Set your API key", code: `export TALONIC_API_KEY="tlnc_live_..."` },
4494
+ { type: "heading", level: 3, id: "step-1-extract", text: "1. Extract a document" },
4495
+ { type: "paragraph", text: "Send a file with an inline schema describing the fields you want:" },
4496
+ { type: "code", language: "bash", title: "curl \u2014 extract an invoice", code: `curl -X POST https://api.talonic.com/v1/extract \\
4497
+ -H "Authorization: Bearer $TALONIC_API_KEY" \\
4475
4498
  -F "file=@invoice.pdf" \\
4476
- -F 'schema={
4477
- "vendor_name": "string",
4478
- "invoice_number": "string",
4479
- "total_amount": "number",
4480
- "due_date": "date",
4481
- "line_items": [{
4482
- "description": "string",
4483
- "quantity": "number",
4484
- "unit_price": "number"
4485
- }]
4486
- }'` },
4487
- { type: "heading", level: 3, id: "step-2", text: "2. Save the schema for reuse" },
4488
- { type: "code", language: "bash", title: "Step 2 \u2014 Save schema", code: `curl -X POST https://api.talonic.com/v1/schemas \\
4489
- -H "Authorization: Bearer tlnc_sk_live_7f3a...x9k2" \\
4490
- -H "Content-Type: application/json" \\
4491
- -d '{
4492
- "name": "Invoice",
4493
- "definition": {
4494
- "vendor_name": "string",
4495
- "invoice_number": "string",
4496
- "total_amount": "number",
4497
- "due_date": "date",
4498
- "line_items": [{
4499
- "description": "string",
4500
- "quantity": "number",
4501
- "unit_price": "number"
4502
- }]
4499
+ -F 'schema={"vendor_name":"string","invoice_number":"string","total_amount":"number","due_date":"date"}'` },
4500
+ { type: "heading", level: 3, id: "step-1-response", text: "Response (200 OK)" },
4501
+ { type: "paragraph", text: "For documents \u22645 pages, you get the extracted data immediately:" },
4502
+ { type: "code", language: "json", title: "Sync response", code: `{
4503
+ "extraction_id": "d1a2b3c4-5678-9abc-def0-1234567890ab",
4504
+ "request_id": "req_x7y8z9a0b1c2d3e4",
4505
+ "status": "complete",
4506
+ "document": {
4507
+ "id": "f0e1d2c3-b4a5-9687-8765-432109876543",
4508
+ "filename": "invoice.pdf",
4509
+ "pages": 2,
4510
+ "size_bytes": 184320,
4511
+ "type_detected": "Invoice"
4512
+ },
4513
+ "data": {
4514
+ "vendor_name": "Acme GmbH",
4515
+ "invoice_number": "INV-2025-0042",
4516
+ "total_amount": 14250.00,
4517
+ "due_date": "2025-04-15"
4518
+ },
4519
+ "confidence": {
4520
+ "overall": 0.96,
4521
+ "fields": {
4522
+ "vendor_name": 0.97,
4523
+ "invoice_number": 0.99,
4524
+ "total_amount": 0.94,
4525
+ "due_date": 0.99
4503
4526
  }
4504
- }'` },
4505
- { type: "heading", level: 3, id: "step-3", text: "3. Query your extraction results" },
4506
- { type: "code", language: "bash", title: "Step 3 \u2014 Retrieve", code: `curl https://api.talonic.com/v1/extractions?schema_id=sch_abc123 \\
4507
- -H "Authorization: Bearer tlnc_sk_live_7f3a...x9k2"` }
4527
+ },
4528
+ "processing": {
4529
+ "duration_ms": 1840,
4530
+ "pages_processed": 2
4531
+ },
4532
+ "links": {
4533
+ "self": "/v1/extractions/d1a2b3c4-5678-9abc-def0-1234567890ab",
4534
+ "document": "/v1/documents/f0e1d2c3-b4a5-9687-8765-432109876543"
4535
+ }
4536
+ }` },
4537
+ { type: "heading", level: 3, id: "step-2-verify", text: "2. Verify it worked" },
4538
+ { type: "paragraph", text: "Retrieve the extraction by ID to confirm the data is persisted:" },
4539
+ { type: "code", language: "bash", title: "Verify extraction", code: `curl https://api.talonic.com/v1/extractions/d1a2b3c4-5678-9abc-def0-1234567890ab \\
4540
+ -H "Authorization: Bearer $TALONIC_API_KEY"` },
4541
+ { type: "paragraph", text: "You should see the same `data` object. The extraction is now stored and queryable across your workspace." },
4542
+ { type: "heading", level: 3, id: "next-steps", text: "Next steps" },
4543
+ { type: "list", items: [
4544
+ "**Reuse schemas** \u2014 save your schema with `POST /v1/schemas`, then pass `schema_id` on future extractions.",
4545
+ "**Large documents** \u2014 files >5 pages return `202 Accepted` with a `poll_url`. See [Processing Modes](extract-processing-mode).",
4546
+ "**Webhooks** \u2014 receive results via `extraction.complete` events instead of polling. See [Webhook Events](webhook-events).",
4547
+ "**Batch mode** \u2014 process at 50% cost with `processing_mode=batch`. See [Batches](batches)."
4548
+ ] }
4508
4549
  ],
4509
4550
  related: [
4510
4551
  { label: "POST /v1/extract", slug: "post-extract" },
4511
4552
  { label: "Schema Formats", slug: "extract-schemas" },
4512
- { label: "List Extractions", slug: "list-extractions" }
4553
+ { label: "Processing Modes", slug: "extract-processing-mode" }
4554
+ ],
4555
+ faq: [
4556
+ { question: "How do I get started with the Talonic API?", answer: "Set your TALONIC_API_KEY environment variable, then send a file with an inline schema to POST /v1/extract. Documents \u22645 pages return results immediately in sync mode." },
4557
+ { question: "Do I need to create a schema first?", answer: "No. You can pass an inline schema as a JSON object on your first extraction. Save it with POST /v1/schemas later for reuse." }
4558
+ ],
4559
+ mentions: ["curl", "quick start", "sync mode", "TALONIC_API_KEY"]
4560
+ },
4561
+ {
4562
+ slug: "pagination",
4563
+ parentSlug: "overview",
4564
+ title: "Pagination",
4565
+ seoTitle: "API Pagination \u2014 Talonic Docs",
4566
+ description: "All list endpoints use cursor-based pagination with cursor, limit, and order parameters. Responses include next_cursor and has_more for iteration.",
4567
+ content: [
4568
+ { type: "paragraph", text: "All list endpoints use cursor-based pagination. Pass a `cursor` token from the previous response to fetch the next page." },
4569
+ {
4570
+ type: "param-table",
4571
+ title: "Request parameters",
4572
+ params: [
4573
+ { name: "limit", type: "integer", description: "Number of items per page (1\u2013100, default 20).", default: "20" },
4574
+ { name: "cursor", type: "string", description: "Opaque cursor token from `pagination.next_cursor` of the previous response. Omit for the first page." },
4575
+ { name: "order", type: "string", description: "Sort direction: `asc` or `desc` (default `desc`, newest first).", default: "desc" }
4576
+ ]
4577
+ },
4578
+ { type: "heading", level: 2, id: "pagination-response", text: "Response shape" },
4579
+ {
4580
+ type: "code",
4581
+ title: "Paginated response",
4582
+ code: `{
4583
+ "data": [
4584
+ { "id": "doc_x9y8z7w6", "name": "invoice-001.pdf", "..." : "..." },
4585
+ { "id": "doc_a1b2c3d4", "name": "invoice-002.pdf", "..." : "..." }
4586
+ ],
4587
+ "pagination": {
4588
+ "total": 1500,
4589
+ "limit": 20,
4590
+ "has_more": true,
4591
+ "next_cursor": "YWJjMTIzfDIwMjYtMDQtMjVUMTQ6MzA6MDAuMDAwWg"
4592
+ }
4593
+ }`
4594
+ },
4595
+ {
4596
+ type: "param-table",
4597
+ title: "Pagination object",
4598
+ params: [
4599
+ { name: "total", type: "integer", description: "Total number of items matching the query." },
4600
+ { name: "limit", type: "integer", description: "Page size used for this request." },
4601
+ { name: "has_more", type: "boolean", description: "`true` if there are more pages after this one." },
4602
+ { name: "next_cursor", type: "string | null", description: "Cursor token to pass in the next request. `null` when on the last page." }
4603
+ ]
4604
+ },
4605
+ { type: "heading", level: 2, id: "pagination-example", text: "Iterating through all pages" },
4606
+ {
4607
+ type: "code",
4608
+ language: "bash",
4609
+ title: "Python \u2014 paginate through all documents",
4610
+ code: `import requests
4611
+
4612
+ API_KEY = "tlnc_live_..."
4613
+ BASE = "https://api.talonic.com/v1"
4614
+ HEADERS = {"Authorization": f"Bearer {API_KEY}"}
4615
+
4616
+ cursor = None
4617
+ all_documents = []
4618
+
4619
+ while True:
4620
+ params = {"limit": 100}
4621
+ if cursor:
4622
+ params["cursor"] = cursor
4623
+
4624
+ resp = requests.get(f"{BASE}/documents", headers=HEADERS, params=params)
4625
+ page = resp.json()
4626
+
4627
+ all_documents.extend(page["data"])
4628
+
4629
+ if not page["pagination"]["has_more"]:
4630
+ break
4631
+ cursor = page["pagination"]["next_cursor"]
4632
+
4633
+ print(f"Fetched {len(all_documents)} documents")`
4634
+ },
4635
+ { type: "callout", text: "Cursors are opaque tokens \u2014 do not parse, modify, or store them long-term. They may change format without notice." }
4636
+ ],
4637
+ related: [
4638
+ { label: "List Documents", slug: "list-documents" },
4639
+ { label: "List Extractions", slug: "list-extractions" },
4640
+ { label: "Rate Limits", slug: "rate-limits" }
4513
4641
  ],
4514
4642
  faq: [
4515
- { question: "How do I get started with the Talonic API?", answer: "Extract a document with an inline schema, save the schema for reuse, then query your extraction results. See the Quick Start guide for curl examples." }
4643
+ { question: "How does Talonic API pagination work?", answer: "Cursor-based. Pass limit (1-100, default 20) and cursor (from pagination.next_cursor). Response includes data[], pagination.has_more, and pagination.next_cursor." },
4644
+ { question: "What is the maximum page size?", answer: "100 items per page. Default is 20." }
4645
+ ],
4646
+ mentions: ["pagination", "cursor", "next_cursor", "has_more", "limit"]
4647
+ },
4648
+ {
4649
+ slug: "idempotency",
4650
+ parentSlug: "overview",
4651
+ title: "Idempotency",
4652
+ seoTitle: "API Idempotency \u2014 Talonic Docs",
4653
+ description: "Use the Idempotency-Key header to safely retry POST requests without creating duplicate extractions. Keys are valid for 24 hours.",
4654
+ content: [
4655
+ { type: "paragraph", text: "Pass an `Idempotency-Key` header on POST requests to safely retry without creating duplicate work. If a request with the same key has already been processed, the API returns the cached response." },
4656
+ {
4657
+ type: "param-table",
4658
+ title: "Idempotency details",
4659
+ params: [
4660
+ { name: "Header", type: "", description: "`Idempotency-Key: <your-unique-key>`" },
4661
+ { name: "Supported endpoints", type: "", description: "`POST /v1/extract` (primary use case). Other POST endpoints may honor it in the future." },
4662
+ { name: "Key format", type: "", description: "Any string up to 255 characters. UUIDs recommended." },
4663
+ { name: "TTL", type: "", description: "24 hours. After expiry, the same key can be reused." },
4664
+ { name: "Scope", type: "", description: "Per API key (customer). The same idempotency key used by different API keys are independent." }
4665
+ ]
4666
+ },
4667
+ { type: "heading", level: 2, id: "idempotency-behavior", text: "Behavior" },
4668
+ { type: "list", items: [
4669
+ "**First request** \u2014 processed normally. The response and extraction ID are cached against the key.",
4670
+ "**Duplicate request** (same key within 24h) \u2014 returns the cached response immediately with HTTP 200. No new extraction is created.",
4671
+ "**Expired key** (after 24h) \u2014 treated as a new request."
4672
+ ] },
4673
+ {
4674
+ type: "code",
4675
+ language: "bash",
4676
+ title: "Example \u2014 safe retry with idempotency",
4677
+ code: `# Generate a unique key per logical operation
4678
+ IDEMPOTENCY_KEY=$(uuidgen)
4679
+
4680
+ curl -X POST https://api.talonic.com/v1/extract \\
4681
+ -H "Authorization: Bearer $TALONIC_API_KEY" \\
4682
+ -H "Idempotency-Key: $IDEMPOTENCY_KEY" \\
4683
+ -F "file=@invoice.pdf" \\
4684
+ -F 'schema={"vendor_name":"string","total_amount":"number"}'
4685
+
4686
+ # Safe to retry on network timeout \u2014 same key returns cached result
4687
+ curl -X POST https://api.talonic.com/v1/extract \\
4688
+ -H "Authorization: Bearer $TALONIC_API_KEY" \\
4689
+ -H "Idempotency-Key: $IDEMPOTENCY_KEY" \\
4690
+ -F "file=@invoice.pdf" \\
4691
+ -F 'schema={"vendor_name":"string","total_amount":"number"}'`
4692
+ },
4693
+ { type: "callout", text: "Always use a new idempotency key for each distinct logical operation. Reusing a key with different parameters will return the cached result from the first request, not process the new parameters." }
4516
4694
  ],
4517
- mentions: ["curl", "schema", "extraction", "document"]
4695
+ related: [
4696
+ { label: "POST /v1/extract", slug: "post-extract" },
4697
+ { label: "Error Codes", slug: "error-codes" }
4698
+ ],
4699
+ faq: [
4700
+ { question: "How do I prevent duplicate extractions on retry?", answer: "Pass an Idempotency-Key header with a unique value (e.g. UUID) on POST /v1/extract. Retries with the same key return the cached result." },
4701
+ { question: "How long are idempotency keys valid?", answer: "24 hours. After that, the same key can be reused and will trigger a new extraction." }
4702
+ ],
4703
+ mentions: ["idempotency", "Idempotency-Key", "retry", "duplicate"]
4518
4704
  }
4519
4705
  ];
4520
4706
 
@@ -7593,7 +7779,27 @@ function verifyWebhook(payload, signature, secret) {
7593
7779
  Buffer.from(signature)
7594
7780
  );
7595
7781
  }`
7596
- }
7782
+ },
7783
+ { type: "heading", level: 2, id: "webhook-test-vectors", text: "Test vectors" },
7784
+ { type: "paragraph", text: "Use these values to verify your signature implementation is correct:" },
7785
+ {
7786
+ type: "code",
7787
+ title: "Test inputs",
7788
+ code: `Secret: whsec_test_secret_do_not_use_in_production
7789
+ Payload: {"event":"extraction.complete","delivery_id":"dlv_test123","timestamp":"2026-01-15T10:00:00Z","data":{"extraction_id":"ext_abc","document_id":"doc_xyz","schema_id":"sch_123","status":"complete","confidence":0.95}}
7790
+ Expected signature: sha256=1e23bdc14b051f268d4fd9544387b51b074186c51c5b6c76ce700956308d168a`
7791
+ },
7792
+ {
7793
+ type: "code",
7794
+ language: "bash",
7795
+ title: "Verify with the command line",
7796
+ code: `# Compute expected signature
7797
+ echo -n '{"event":"extraction.complete","delivery_id":"dlv_test123","timestamp":"2026-01-15T10:00:00Z","data":{"extraction_id":"ext_abc","document_id":"doc_xyz","schema_id":"sch_123","status":"complete","confidence":0.95}}' \\
7798
+ | openssl dgst -sha256 -hmac "whsec_test_secret_do_not_use_in_production"
7799
+
7800
+ # Output: 1e23bdc14b051f268d4fd9544387b51b074186c51c5b6c76ce700956308d168a`
7801
+ },
7802
+ { type: "callout", text: "The test secret above is for development only. Never use it in production. Your real webhook secret is generated when you configure a webhook in the dashboard." }
7597
7803
  ],
7598
7804
  related: [
7599
7805
  { label: "Webhook Events", slug: "webhook-events" },
@@ -17098,21 +17304,36 @@ var sections44 = [
17098
17304
  parentSlug: "errors-rate-limits",
17099
17305
  title: "Error Format",
17100
17306
  seoTitle: "API Error Format \u2014 Talonic Docs",
17101
- description: "All Talonic API errors return a consistent JSON structure with a machine-readable code, human-readable message, HTTP status, retryable flag, and request ID.",
17307
+ description: "All Talonic API errors return a consistent JSON envelope with a machine-readable code, human-readable message, HTTP status, retryable flag, request ID, and timestamp.",
17102
17308
  content: [
17103
- { type: "paragraph", text: "All errors return a consistent JSON structure with a machine-readable code and a human-readable message." },
17309
+ { type: "paragraph", text: "All errors return a consistent JSON envelope. The `retryable` field tells you whether the request can be retried with the same parameters." },
17104
17310
  {
17105
17311
  type: "code",
17106
- title: "Error response shape",
17312
+ title: "Error response envelope",
17107
17313
  code: `{
17108
- "error": {
17109
- "code": "invalid_schema",
17110
- "message": "Schema definition is missing required 'type' field at path 'line_items.items'.",
17111
- "status": 400,
17112
- "retryable": false,
17113
- "request_id": "req_x7y8z9a0"
17114
- }
17314
+ "statusCode": 400,
17315
+ "code": "VALIDATION_ERROR",
17316
+ "error": "Bad Request",
17317
+ "message": "Schema definition is missing required 'type' field at path 'line_items.items'.",
17318
+ "retryable": false,
17319
+ "request_id": "req_x7y8z9a0b1c2d3e4",
17320
+ "timestamp": "2026-04-25T14:30:00.000Z",
17321
+ "path": "/v1/schemas"
17115
17322
  }`
17323
+ },
17324
+ {
17325
+ type: "param-table",
17326
+ title: "Envelope fields",
17327
+ params: [
17328
+ { name: "statusCode", type: "integer", description: "HTTP status code (matches the response status)." },
17329
+ { name: "code", type: "string", description: "Machine-readable error code (e.g. `VALIDATION_ERROR`, `RATE_LIMIT_EXCEEDED`)." },
17330
+ { name: "error", type: "string", description: 'HTTP status text (e.g. "Bad Request", "Too Many Requests").' },
17331
+ { name: "message", type: "string", description: "Human-readable explanation of what went wrong." },
17332
+ { name: "retryable", type: "boolean", description: "`true` if the same request may succeed on retry (e.g. rate limits, timeouts)." },
17333
+ { name: "request_id", type: "string", description: "Unique request identifier for support debugging. Prefix: `req_`." },
17334
+ { name: "timestamp", type: "string", description: "ISO 8601 timestamp of when the error occurred." },
17335
+ { name: "path", type: "string", description: "The request path that produced the error." }
17336
+ ]
17116
17337
  }
17117
17338
  ],
17118
17339
  related: [
@@ -17120,41 +17341,66 @@ var sections44 = [
17120
17341
  { label: "Rate Limits", slug: "rate-limits" }
17121
17342
  ],
17122
17343
  faq: [
17123
- { question: "What does a Talonic API error look like?", answer: "A JSON object with error.code (machine-readable), error.message (human-readable), error.status (HTTP status), error.retryable (boolean), and error.request_id." }
17344
+ { question: "What does a Talonic API error look like?", answer: "A JSON object with statusCode, code (machine-readable), message (human-readable), retryable (boolean), request_id, timestamp, and path." },
17345
+ { question: "How do I know if an error is retryable?", answer: "Check the retryable field in the error response. If true, you can retry with exponential backoff." }
17124
17346
  ],
17125
- mentions: ["error format", "JSON error", "request_id"]
17347
+ mentions: ["error format", "JSON error", "request_id", "retryable"]
17126
17348
  },
17127
17349
  {
17128
17350
  slug: "error-codes",
17129
17351
  parentSlug: "errors-rate-limits",
17130
17352
  title: "Error Codes",
17131
17353
  seoTitle: "API Error Codes Reference \u2014 Talonic Docs",
17132
- description: "Complete reference of Talonic API error codes including bad_request, invalid_schema, unauthorized, not_found, rate_limited, and more with HTTP status mappings.",
17354
+ description: "Complete reference of Talonic API error codes with HTTP status, retryable classification, and recommended handling for each error type.",
17133
17355
  content: [
17134
- { type: "paragraph", text: "Error codes returned by the Talonic API:" },
17356
+ { type: "paragraph", text: "Error codes returned by the Talonic API, grouped by whether they are retryable:" },
17357
+ { type: "heading", level: 2, id: "permanent-errors", text: "Permanent errors (do not retry)" },
17135
17358
  { type: "list", items: [
17136
- "**400** `bad_request` \u2014 The request body is malformed or missing required fields.",
17359
+ "**400** `VALIDATION_ERROR` \u2014 The request body is malformed or missing required fields.",
17137
17360
  "**400** `invalid_schema` \u2014 The schema definition is invalid or contains unsupported types.",
17138
17361
  "**400** `invalid_file` \u2014 The uploaded file is corrupt, empty, or in an unsupported format.",
17139
- "**401** `unauthorized` \u2014 Missing or invalid API key.",
17140
- "**403** `forbidden` \u2014 The API key does not have permission for this operation.",
17141
- "**404** `not_found` \u2014 The requested resource does not exist.",
17142
- "**409** `conflict` \u2014 The resource has been modified. Retry with the latest version.",
17143
- "**413** `file_too_large` \u2014 The uploaded file exceeds the 50MB size limit.",
17144
- "**422** `unprocessable` \u2014 The document could not be parsed. Try a different file format.",
17145
- "**429** `rate_limited` \u2014 Rate limit exceeded. Check response headers for reset time.",
17146
- "**500** `internal_error` \u2014 An unexpected error occurred. This is retryable.",
17362
+ "**401** `AUTH_REQUIRED` \u2014 Missing or invalid API key.",
17363
+ "**401** `TOKEN_EXPIRED` \u2014 The API key has expired. Generate a new one from the dashboard.",
17364
+ "**402** `INSUFFICIENT_CREDITS` \u2014 Your workspace has no remaining credits. Top up from Settings \u2192 Billing.",
17365
+ "**403** `INSUFFICIENT_PERMISSIONS` \u2014 The API key does not have the required scope for this operation.",
17366
+ "**404** `RESOURCE_NOT_FOUND` \u2014 The requested resource does not exist.",
17367
+ "**409** `DUPLICATE_RESOURCE` \u2014 A resource with this identifier already exists.",
17368
+ "**413** `FILE_TOO_LARGE` \u2014 The uploaded file exceeds the maximum size limit (500 MB).",
17369
+ "**422** `EXTRACTION_FAILED` \u2014 The document could not be processed. Try a different format or check the file."
17370
+ ] },
17371
+ { type: "heading", level: 2, id: "retryable-errors", text: "Retryable errors (retry with backoff)" },
17372
+ { type: "list", items: [
17373
+ "**429** `RATE_LIMIT_EXCEEDED` \u2014 Daily rate limit reached. Wait until `X-RateLimit-Reset` before retrying.",
17374
+ "**429** `LLM_RATE_LIMITED` \u2014 Upstream AI provider rate limit. Retry after 30\u201360 seconds.",
17375
+ "**500** `INTERNAL_ERROR` \u2014 An unexpected server error occurred. Retryable with backoff.",
17376
+ "**500** `LLM_TIMEOUT` \u2014 Upstream AI provider timed out. Retryable with backoff.",
17377
+ "**500** `LLM_UNAVAILABLE` \u2014 Upstream AI provider temporarily unavailable.",
17378
+ "**500** `OCR_FAILED` \u2014 Document OCR failed. Retryable \u2014 may succeed on retry.",
17379
+ "**500** `EXTRACTION_TIMEOUT` \u2014 Extraction exceeded the time limit. Retryable for smaller documents.",
17147
17380
  "**503** `service_unavailable` \u2014 The service is temporarily unavailable. Retry with backoff."
17148
- ] }
17381
+ ] },
17382
+ { type: "heading", level: 2, id: "backoff-strategy", text: "Recommended backoff strategy" },
17383
+ { type: "paragraph", text: "For retryable errors, use exponential backoff with jitter:" },
17384
+ { type: "list", ordered: true, items: [
17385
+ "1st retry \u2014 wait 1 second",
17386
+ "2nd retry \u2014 wait 2 seconds",
17387
+ "3rd retry \u2014 wait 4 seconds",
17388
+ "4th retry \u2014 wait 8 seconds",
17389
+ "5th retry (max) \u2014 wait 16 seconds"
17390
+ ] },
17391
+ { type: "paragraph", text: "Add random jitter (\xB120%) to avoid thundering herd. For `429` errors specifically, respect the `X-RateLimit-Reset` header instead of using fixed backoff \u2014 it tells you exactly when the window resets (ISO 8601 timestamp, midnight UTC)." },
17392
+ { type: "callout", text: "The API does not send a `Retry-After` header. For rate limits, use `X-RateLimit-Reset` to determine when to retry. For other retryable errors, use exponential backoff." }
17149
17393
  ],
17150
17394
  related: [
17151
17395
  { label: "Error Format", slug: "error-format" },
17152
17396
  { label: "Rate Limits", slug: "rate-limits" }
17153
17397
  ],
17154
17398
  faq: [
17155
- { question: "What error codes does the Talonic API return?", answer: "Standard HTTP status codes (400, 401, 403, 404, 409, 413, 422, 429, 500, 503) with machine-readable codes like bad_request, invalid_schema, unauthorized, rate_limited, etc." }
17399
+ { question: "What error codes does the Talonic API return?", answer: "Errors use HTTP status codes (400\u2013503) with machine-readable codes like VALIDATION_ERROR, RATE_LIMIT_EXCEEDED, INSUFFICIENT_CREDITS, INTERNAL_ERROR, etc." },
17400
+ { question: "Which errors should I retry?", answer: "Retry errors with retryable: true \u2014 typically 429 (rate limited), 500 (internal/timeout), and 503 (unavailable). Never retry 400, 401, 402, 403, 404, or 413." },
17401
+ { question: "Does the API send a Retry-After header?", answer: "No. For rate limits, use X-RateLimit-Reset (ISO 8601 timestamp). For other retryable errors, use exponential backoff starting at 1 second." }
17156
17402
  ],
17157
- mentions: ["error codes", "HTTP status", "bad_request", "rate_limited"]
17403
+ mentions: ["error codes", "HTTP status", "retryable", "backoff", "RATE_LIMIT_EXCEEDED", "INSUFFICIENT_CREDITS"]
17158
17404
  },
17159
17405
  {
17160
17406
  slug: "rate-limits",
@@ -17166,15 +17412,15 @@ var sections44 = [
17166
17412
  { type: "paragraph", text: "API rate limits depend on your plan tier. Limits are applied per API key on a rolling daily window (UTC midnight reset)." },
17167
17413
  { type: "paragraph", text: "Rate limits by plan:" },
17168
17414
  { type: "list", items: [
17169
- "**Free** \u2014 50 extractions/day, 5/min burst, 10 MB max file size",
17170
- "**Pro** \u2014 2,000 extractions/day, 30/min burst, 50 MB max file size",
17171
- "**Enterprise** \u2014 Unlimited extractions, custom burst rate, custom file size"
17415
+ "**Free** \u2014 50 extractions/day, 5/min burst, 20 MB max file size",
17416
+ "**Pro** \u2014 2,000 extractions/day, 30/min burst, 100 MB max file size",
17417
+ "**Enterprise** \u2014 Unlimited extractions, custom burst rate, 500 MB max file size"
17172
17418
  ] },
17173
17419
  { type: "paragraph", text: "Every API response includes rate limit headers:" },
17174
17420
  { type: "list", items: [
17175
17421
  "`X-RateLimit-Limit` \u2014 Maximum number of requests allowed in the current window.",
17176
17422
  "`X-RateLimit-Remaining` \u2014 Number of requests remaining in the current window.",
17177
- "`X-RateLimit-Reset` \u2014 Unix timestamp when the rate limit window resets."
17423
+ "`X-RateLimit-Reset` \u2014 ISO 8601 timestamp when the rate limit window resets (midnight UTC)."
17178
17424
  ] },
17179
17425
  {
17180
17426
  type: "code",
@@ -17183,7 +17429,7 @@ var sections44 = [
17183
17429
  code: `HTTP/1.1 200 OK
17184
17430
  X-RateLimit-Limit: 2000
17185
17431
  X-RateLimit-Remaining: 1847
17186
- X-RateLimit-Reset: 1726358400`
17432
+ X-RateLimit-Reset: 2026-04-26T00:00:00.000Z`
17187
17433
  },
17188
17434
  { type: "callout", text: "When you receive a `429` response, wait until the `X-RateLimit-Reset` timestamp before retrying. Implement exponential backoff for the best experience." }
17189
17435
  ],
package/dist/index.js CHANGED
@@ -6378,7 +6378,9 @@ var API_NAV_SECTIONS = [
6378
6378
  { id: "introduction", label: "Introduction" },
6379
6379
  { id: "authentication", label: "Authentication" },
6380
6380
  { id: "base-url", label: "Base URL" },
6381
- { id: "quick-start", label: "Quick Start" }
6381
+ { id: "quick-start", label: "Quick Start" },
6382
+ { id: "pagination", label: "Pagination" },
6383
+ { id: "idempotency", label: "Idempotency" }
6382
6384
  ] },
6383
6385
  { id: "extract", label: "Extract", children: [
6384
6386
  { id: "post-extract", label: "POST /v1/extract" },