@talonic/docs 0.6.1 → 0.7.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/index.js CHANGED
@@ -591,14 +591,21 @@ var NAV_SECTIONS = [
591
591
  ]
592
592
  },
593
593
  {
594
- id: "exports",
595
- label: "Exports",
594
+ id: "delivery",
595
+ label: "Delivery",
596
596
  children: [
597
+ { id: "delivery-overview", label: "Overview" },
597
598
  { id: "list-destinations", label: "List Destinations" },
598
599
  { id: "create-destination", label: "Create Destination" },
599
- { id: "manage-destination", label: "Get / Delete Destination" },
600
- { id: "list-triggers", label: "List Triggers" },
601
- { id: "create-trigger", label: "Create Trigger" }
600
+ { id: "manage-destination", label: "Get / Update / Delete" },
601
+ { id: "test-destination", label: "Test Destination" },
602
+ { id: "list-bindings", label: "List Bindings" },
603
+ { id: "create-binding", label: "Create Binding" },
604
+ { id: "manage-binding", label: "Get / Update / Delete" },
605
+ { id: "delivery-items", label: "Items (History)" },
606
+ { id: "delivery-dlq", label: "Dead-Letter Queue" },
607
+ { id: "delivery-events", label: "Outbox Events" },
608
+ { id: "delivery-catalog", label: "Catalog" }
602
609
  ]
603
610
  },
604
611
  {
@@ -2283,7 +2290,7 @@ function ApiReference({ LinkComponent }) {
2283
2290
  }
2284
2291
  ) }),
2285
2292
  /* @__PURE__ */ jsx5(SectionHeading, { id: "routing", children: "Routing Rules" }),
2286
- /* @__PURE__ */ jsx5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-6", children: "Routing rules automatically direct documents to schemas, reviewers, or export destinations based on configurable conditions." }),
2293
+ /* @__PURE__ */ jsx5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-6", children: "Routing rules automatically direct documents to schemas, reviewers, or delivery destinations based on configurable conditions." }),
2287
2294
  /* @__PURE__ */ jsx5("div", { id: "list-routing-rules", className: "scroll-mt-6", children: /* @__PURE__ */ jsx5(
2288
2295
  EndpointBlock,
2289
2296
  {
@@ -2342,108 +2349,250 @@ function ApiReference({ LinkComponent }) {
2342
2349
  /* @__PURE__ */ jsx5(EndpointBlock, { method: "DELETE", path: "/v1/routing-rules/:id", summary: "Delete a routing rule." })
2343
2350
  ] })
2344
2351
  ] }),
2345
- /* @__PURE__ */ jsx5(SectionHeading, { id: "exports", children: "Exports" }),
2346
- /* @__PURE__ */ jsx5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-6", children: "Configure export destinations (S3, webhook, SFTP) and triggers that automatically push structured data when conditions are met." }),
2352
+ /* @__PURE__ */ jsx5(SectionHeading, { id: "delivery", children: "Delivery" }),
2353
+ /* @__PURE__ */ jsxs5("div", { id: "delivery-overview", className: "scroll-mt-6", children: [
2354
+ /* @__PURE__ */ jsxs5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-4", children: [
2355
+ "Configure outbound delivery. Emit signals (",
2356
+ /* @__PURE__ */ jsx5(InlineCode, { children: "document.extracted" }),
2357
+ ",",
2358
+ " ",
2359
+ /* @__PURE__ */ jsx5(InlineCode, { children: "run.dataspace.completed" }),
2360
+ ", ",
2361
+ /* @__PURE__ */ jsx5(InlineCode, { children: "result.approved" }),
2362
+ ", \u2026) are routed through ",
2363
+ /* @__PURE__ */ jsx5("strong", { children: "bindings" }),
2364
+ " that join a signal filter to a",
2365
+ " ",
2366
+ /* @__PURE__ */ jsx5("strong", { children: "deliverable resolver" }),
2367
+ ", a ",
2368
+ /* @__PURE__ */ jsx5("strong", { children: "serializer" }),
2369
+ ", and a",
2370
+ " ",
2371
+ /* @__PURE__ */ jsx5("strong", { children: "destination" }),
2372
+ ". Slice-1 ships the ",
2373
+ /* @__PURE__ */ jsx5(InlineCode, { children: "webhook" }),
2374
+ " ",
2375
+ "connector with HMAC-signed payloads, idempotency keys, SSRF guard, payload caps, and a fixed retry ladder; S3, SFTP, Sheets, Drive, and Email arrive in later slices."
2376
+ ] }),
2377
+ /* @__PURE__ */ jsxs5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-6", children: [
2378
+ "Every attempt is recorded in the history log (",
2379
+ /* @__PURE__ */ jsx5(InlineCode, { children: "/v1/delivery/items" }),
2380
+ "). Terminal failures land in the dead-letter queue (",
2381
+ /* @__PURE__ */ jsx5(InlineCode, { children: "/v1/delivery/dlq" }),
2382
+ ") and are replayable. The raw outbox is inspectable at",
2383
+ " ",
2384
+ /* @__PURE__ */ jsx5(InlineCode, { children: "/v1/delivery/events" }),
2385
+ ". Use",
2386
+ " ",
2387
+ /* @__PURE__ */ jsx5(InlineCode, { children: "/v1/delivery/catalog/*" }),
2388
+ " to discover available signals, deliverables, serializers, and connectors \u2014 the catalog drives the compatibility-triangle validator that runs on every binding create/update."
2389
+ ] })
2390
+ ] }),
2347
2391
  /* @__PURE__ */ jsx5("div", { id: "list-destinations", className: "scroll-mt-6", children: /* @__PURE__ */ jsx5(
2348
2392
  EndpointBlock,
2349
2393
  {
2350
2394
  method: "GET",
2351
- path: "/v1/exports/destinations",
2352
- summary: "List all configured export destinations.",
2353
- children: /* @__PURE__ */ jsx5(CodeBlock, { title: "Response", children: `{
2354
- "data": [
2355
- {
2356
- "id": "dest_9x2k4m",
2357
- "name": "Production S3",
2358
- "type": "s3",
2359
- "config": { "bucket": "my-exports", "prefix": "structured/" },
2360
- "created_at": "2024-09-01T00:00:00Z"
2361
- }
2362
- ]
2363
- }` })
2395
+ path: "/v1/delivery/destinations",
2396
+ summary: "List delivery destinations.",
2397
+ children: /* @__PURE__ */ jsx5(CodeBlock, { title: "Response", children: `[
2398
+ {
2399
+ "id": "7f8a2b44-...",
2400
+ "name": "Analytics webhook",
2401
+ "type": "webhook",
2402
+ "config": { "url": "https://example.com/hook", "headers": {} },
2403
+ "signing_secret": "***",
2404
+ "payload_cap_bytes": null,
2405
+ "is_active": true,
2406
+ "last_delivery_at": "2026-04-23T10:21:00Z",
2407
+ "last_delivery_status": "succeeded",
2408
+ "created_at": "2026-04-15T00:00:00Z",
2409
+ "updated_at": "2026-04-23T10:21:00Z"
2410
+ }
2411
+ ]` })
2364
2412
  }
2365
2413
  ) }),
2366
2414
  /* @__PURE__ */ jsx5("div", { id: "create-destination", className: "scroll-mt-6", children: /* @__PURE__ */ jsxs5(
2367
2415
  EndpointBlock,
2368
2416
  {
2369
2417
  method: "POST",
2370
- path: "/v1/exports/destinations",
2371
- summary: "Create a new export destination.",
2418
+ path: "/v1/delivery/destinations",
2419
+ summary: "Create a delivery destination.",
2372
2420
  children: [
2373
2421
  /* @__PURE__ */ jsx5(
2374
2422
  ParamTable,
2375
2423
  {
2376
2424
  title: "Body parameters",
2377
2425
  params: [
2378
- { name: "name", type: "string", required: true, description: "Destination name." },
2379
- { name: "type", type: "string", required: true, description: "Type: s3, webhook, sftp." },
2380
- { name: "config", type: "object", required: true, description: "Type-specific configuration (bucket, url, host, etc.)." }
2426
+ { name: "name", type: "string", required: true, description: "Human-readable name." },
2427
+ { name: "type", type: "string", required: true, description: "Connector type. Slice-1 ships `webhook`." },
2428
+ { name: "config", type: "object", description: "Connector-specific configuration (e.g. `{ url, headers }`)." },
2429
+ { name: "auth_config", type: "object", description: "Connector-specific credentials. Never echoed back in full." },
2430
+ { name: "signing_secret", type: "string", description: "HMAC secret for connectors that sign outbound bodies." },
2431
+ { name: "payload_cap_bytes", type: "integer", description: "Per-destination TransportWrapper cap override." },
2432
+ { name: "is_active", type: "boolean", description: "Defaults to true." }
2381
2433
  ]
2382
2434
  }
2383
2435
  ),
2384
2436
  /* @__PURE__ */ jsx5(CodeBlock, { title: "Response (201)", children: `{
2385
- "id": "dest_9x2k4m",
2386
- "name": "Production S3",
2387
- "type": "s3",
2388
- "config": { "bucket": "my-exports", "prefix": "structured/" }
2437
+ "id": "7f8a2b44-...",
2438
+ "name": "Analytics webhook",
2439
+ "type": "webhook",
2440
+ "config": { "url": "https://example.com/hook" },
2441
+ "signing_secret": "***",
2442
+ "is_active": true,
2443
+ "created_at": "2026-04-23T10:21:00Z",
2444
+ "updated_at": "2026-04-23T10:21:00Z"
2389
2445
  }` })
2390
2446
  ]
2391
2447
  }
2392
2448
  ) }),
2393
2449
  /* @__PURE__ */ jsxs5("div", { id: "manage-destination", className: "scroll-mt-6", children: [
2394
- /* @__PURE__ */ jsx5(SubHeading, { id: "manage-destination", children: "Get / Delete Destination" }),
2450
+ /* @__PURE__ */ jsx5(SubHeading, { id: "manage-destination", children: "Get / Update / Delete Destination" }),
2395
2451
  /* @__PURE__ */ jsxs5("div", { className: "space-y-2 mb-6", children: [
2396
- /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/exports/destinations/:id", summary: "Get destination details." }),
2397
- /* @__PURE__ */ jsx5(EndpointBlock, { method: "DELETE", path: "/v1/exports/destinations/:id", summary: "Delete a destination and its triggers." })
2452
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/delivery/destinations/:id", summary: "Get destination detail." }),
2453
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "PUT", path: "/v1/delivery/destinations/:id", summary: "Partial update \u2014 only supplied fields are written." }),
2454
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "DELETE", path: "/v1/delivery/destinations/:id", summary: "Delete a destination. Cascading bindings are removed." })
2398
2455
  ] })
2399
2456
  ] }),
2400
- /* @__PURE__ */ jsx5("div", { id: "list-triggers", className: "scroll-mt-6", children: /* @__PURE__ */ jsx5(
2457
+ /* @__PURE__ */ jsx5("div", { id: "test-destination", className: "scroll-mt-6", children: /* @__PURE__ */ jsxs5(
2401
2458
  EndpointBlock,
2402
2459
  {
2403
- method: "GET",
2404
- path: "/v1/exports/triggers",
2405
- summary: "List all export triggers.",
2406
- children: /* @__PURE__ */ jsx5(CodeBlock, { title: "Response", children: `{
2407
- "data": [
2408
- {
2409
- "id": "trig_3n7k9m",
2410
- "name": "On extraction complete",
2411
- "destination_id": "dest_9x2k4m",
2412
- "event": "extraction.completed",
2413
- "conditions": { "schema_id": "schema_fin_001" }
2414
- }
2415
- ]
2460
+ method: "POST",
2461
+ path: "/v1/delivery/destinations/:id/test",
2462
+ summary: "Live-ping a destination through the full transport envelope.",
2463
+ children: [
2464
+ /* @__PURE__ */ jsxs5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-4", children: [
2465
+ "Exercises the complete delivery envelope (SSRF guard, payload cap, rate limit \u2014 retry ladder is disabled, ",
2466
+ /* @__PURE__ */ jsx5(InlineCode, { children: "max_attempts: 1" }),
2467
+ ") with a tiny test payload."
2468
+ ] }),
2469
+ /* @__PURE__ */ jsx5(CodeBlock, { title: "Response", children: `{
2470
+ "success": true,
2471
+ "httpStatus": 200,
2472
+ "durationMs": 284,
2473
+ "message": null
2416
2474
  }` })
2475
+ ]
2417
2476
  }
2418
2477
  ) }),
2419
- /* @__PURE__ */ jsx5("div", { id: "create-trigger", className: "scroll-mt-6", children: /* @__PURE__ */ jsxs5(
2478
+ /* @__PURE__ */ jsx5("div", { id: "list-bindings", className: "scroll-mt-6", children: /* @__PURE__ */ jsx5(
2479
+ EndpointBlock,
2480
+ {
2481
+ method: "GET",
2482
+ path: "/v1/delivery/bindings",
2483
+ summary: "List delivery bindings.",
2484
+ children: /* @__PURE__ */ jsx5(CodeBlock, { title: "Response", children: `[
2485
+ {
2486
+ "id": "4c2e1a39-...",
2487
+ "name": "Extracted docs -> analytics",
2488
+ "signal_filter": { "event_type": "document.extracted" },
2489
+ "deliverable_type": "document_meta",
2490
+ "destination_id": "7f8a2b44-...",
2491
+ "serializer_format": "json",
2492
+ "is_active": true
2493
+ }
2494
+ ]` })
2495
+ }
2496
+ ) }),
2497
+ /* @__PURE__ */ jsx5("div", { id: "create-binding", className: "scroll-mt-6", children: /* @__PURE__ */ jsxs5(
2420
2498
  EndpointBlock,
2421
2499
  {
2422
2500
  method: "POST",
2423
- path: "/v1/exports/triggers",
2424
- summary: "Create a new export trigger.",
2501
+ path: "/v1/delivery/bindings",
2502
+ summary: "Create a delivery binding.",
2425
2503
  children: [
2504
+ /* @__PURE__ */ jsxs5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-4", children: [
2505
+ "Runs the compatibility-triangle validator: the ",
2506
+ /* @__PURE__ */ jsx5(InlineCode, { children: "signal_filter" }),
2507
+ " must be well-formed, the ",
2508
+ /* @__PURE__ */ jsx5(InlineCode, { children: "deliverable_type" }),
2509
+ " must resolve to a registered resolver, the ",
2510
+ /* @__PURE__ */ jsx5(InlineCode, { children: "serializer_format" }),
2511
+ " must resolve to a registered serializer, and the serializer must support the resolver's shape."
2512
+ ] }),
2426
2513
  /* @__PURE__ */ jsx5(
2427
2514
  ParamTable,
2428
2515
  {
2429
2516
  title: "Body parameters",
2430
2517
  params: [
2431
- { name: "name", type: "string", required: true, description: "Trigger name." },
2432
- { name: "destination_id", type: "string", required: true, description: "Target destination." },
2433
- { name: "event", type: "string", required: true, description: "Event type: extraction.completed, job.completed." },
2434
- { name: "conditions", type: "object", description: "Optional conditions to filter events." }
2518
+ { name: "name", type: "string", required: true, description: "Human-readable name." },
2519
+ { name: "signal_filter", type: "object", required: true, description: "Shape: `{ event_type, match? }`. Match is an equality filter on payload keys." },
2520
+ { name: "deliverable_type", type: "string", required: true, description: "Registered resolver (`/v1/delivery/catalog/deliverables`)." },
2521
+ { name: "destination_id", type: "uuid", required: true, description: "Destination to deliver to." },
2522
+ { name: "serializer_format", type: "string", required: true, description: "One of `json`, `ndjson`, `csv`, `csv_file`, `xlsx`, `rows`, `graph`, `raw`, `md`, `txt`." },
2523
+ { name: "serializer_config", type: "object", description: "Format-specific options (delimiter, include_header, etc.)." },
2524
+ { name: "field_map", type: "object", description: "Declarative projection: `{ rules, static, drop }`. Drop \u2192 rename \u2192 static in fixed order." },
2525
+ { name: "delivery_policy", type: "object", description: "Retry/timeout overrides. Defaults to 6 attempts, `[5s, 30s, 2min, 10min, 1h]`." },
2526
+ { name: "is_active", type: "boolean", description: "Defaults to true." }
2435
2527
  ]
2436
2528
  }
2437
- ),
2438
- /* @__PURE__ */ jsx5(CodeBlock, { title: "Response (201)", children: `{
2439
- "id": "trig_3n7k9m",
2440
- "name": "On extraction complete",
2441
- "destination_id": "dest_9x2k4m",
2442
- "event": "extraction.completed"
2443
- }` })
2529
+ )
2444
2530
  ]
2445
2531
  }
2446
2532
  ) }),
2533
+ /* @__PURE__ */ jsxs5("div", { id: "manage-binding", className: "scroll-mt-6", children: [
2534
+ /* @__PURE__ */ jsx5(SubHeading, { id: "manage-binding", children: "Get / Update / Delete Binding" }),
2535
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-2 mb-6", children: [
2536
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/delivery/bindings/:id", summary: "Get binding detail." }),
2537
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "PUT", path: "/v1/delivery/bindings/:id", summary: "Partial update. Re-runs the compatibility-triangle validator on changed fields." }),
2538
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "DELETE", path: "/v1/delivery/bindings/:id", summary: "Delete a binding." }),
2539
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "POST", path: "/v1/delivery/bindings/:id/preview", summary: "Synthetic-signal dry run. Stubbed in slice 1." })
2540
+ ] })
2541
+ ] }),
2542
+ /* @__PURE__ */ jsxs5("div", { id: "delivery-items", className: "scroll-mt-6", children: [
2543
+ /* @__PURE__ */ jsx5(SubHeading, { id: "delivery-items", children: "Items (History)" }),
2544
+ /* @__PURE__ */ jsxs5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-4", children: [
2545
+ "One row per delivery attempt. The processor writes ",
2546
+ /* @__PURE__ */ jsx5(InlineCode, { children: "in_flight" }),
2547
+ " at start, then updates to ",
2548
+ /* @__PURE__ */ jsx5(InlineCode, { children: "succeeded" }),
2549
+ " or ",
2550
+ /* @__PURE__ */ jsx5(InlineCode, { children: "failed" }),
2551
+ ". Replay generates a new attempt with a new idempotency key \u2014 history is append-only."
2552
+ ] }),
2553
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-2 mb-6", children: [
2554
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/delivery/items", summary: "List attempts. Filter by binding_id, destination_id, status. Paginated." }),
2555
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/delivery/items/:id", summary: "Attempt detail with request/response bodies." }),
2556
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "POST", path: "/v1/delivery/items/:id/replay", summary: "Re-enqueue. Returns `{ enqueued, idempotency_key }`." })
2557
+ ] })
2558
+ ] }),
2559
+ /* @__PURE__ */ jsxs5("div", { id: "delivery-dlq", className: "scroll-mt-6", children: [
2560
+ /* @__PURE__ */ jsx5(SubHeading, { id: "delivery-dlq", children: "Dead-Letter Queue" }),
2561
+ /* @__PURE__ */ jsx5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-4", children: "Terminal failures after retry exhaustion (or permanent 4xx errors) land here. Replay enqueues a fresh attempt; dismiss removes the row from the queue without replaying." }),
2562
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-2 mb-6", children: [
2563
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/delivery/dlq", summary: "List dead-letter rows. Filter by binding_id, error_code." }),
2564
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/delivery/dlq/:id", summary: "Dead-letter detail." }),
2565
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "POST", path: "/v1/delivery/dlq/:id/replay", summary: "Re-enqueue a dead-letter row. Row remains in queue for audit." }),
2566
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "DELETE", path: "/v1/delivery/dlq/:id", summary: "Dismiss the row." })
2567
+ ] })
2568
+ ] }),
2569
+ /* @__PURE__ */ jsxs5("div", { id: "delivery-events", className: "scroll-mt-6", children: [
2570
+ /* @__PURE__ */ jsx5(SubHeading, { id: "delivery-events", children: "Outbox Events" }),
2571
+ /* @__PURE__ */ jsxs5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-4", children: [
2572
+ "Raw outbox rows with their processing status (",
2573
+ /* @__PURE__ */ jsx5(InlineCode, { children: "enqueued" }),
2574
+ ",",
2575
+ " ",
2576
+ /* @__PURE__ */ jsx5(InlineCode, { children: "no-subscribers" }),
2577
+ ", ",
2578
+ /* @__PURE__ */ jsx5(InlineCode, { children: "failed" }),
2579
+ "). Useful for debugging binding matchers. Event IDs are BIGSERIAL (strings)."
2580
+ ] }),
2581
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-2 mb-6", children: [
2582
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/delivery/events", summary: "List outbox rows. Filter by event_type. Paginated." }),
2583
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "POST", path: "/v1/delivery/events/:id/replay", summary: "Clear processed_at/processing_status so the poller re-picks the row." })
2584
+ ] })
2585
+ ] }),
2586
+ /* @__PURE__ */ jsxs5("div", { id: "delivery-catalog", className: "scroll-mt-6", children: [
2587
+ /* @__PURE__ */ jsx5(SubHeading, { id: "delivery-catalog", children: "Catalog" }),
2588
+ /* @__PURE__ */ jsx5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-4", children: "Introspect the four registries that drive the binding compatibility-triangle. Populate your binding-editor dropdowns from these endpoints rather than hardcoding lists." }),
2589
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-2 mb-6", children: [
2590
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/delivery/catalog/signals", summary: "All DeliveryEventType discriminants." }),
2591
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/delivery/catalog/deliverables", summary: "Registered resolvers with compatible_signals and shape." }),
2592
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/delivery/catalog/serializers", summary: "Registered serializers with supports_kinds (probed)." }),
2593
+ /* @__PURE__ */ jsx5(EndpointBlock, { method: "GET", path: "/v1/delivery/catalog/connectors", summary: "Registered connectors with capabilities()." })
2594
+ ] })
2595
+ ] }),
2447
2596
  /* @__PURE__ */ jsx5(SectionHeading, { id: "review", children: "Review" }),
2448
2597
  /* @__PURE__ */ jsx5("p", { className: "text-[15px] text-void-text-secondary leading-relaxed mb-6", children: "The review queue surfaces extraction results that need human validation. Approve, reject, or batch-process items programmatically." }),
2449
2598
  /* @__PURE__ */ jsx5("div", { id: "list-review", className: "scroll-mt-6", children: /* @__PURE__ */ jsxs5(
@@ -3369,11 +3518,13 @@ var NAV_SECTIONS2 = [
3369
3518
  },
3370
3519
  {
3371
3520
  id: "delivery",
3372
- label: "Outputs",
3521
+ label: "Delivery",
3373
3522
  children: [
3523
+ { id: "delivery-pipeline", label: "How Delivery Works" },
3374
3524
  { id: "destinations", label: "Destinations" },
3375
- { id: "field-mappings", label: "Field Mappings" },
3376
- { id: "export-triggers", label: "Triggers" }
3525
+ { id: "bindings", label: "Bindings" },
3526
+ { id: "signals-catalog", label: "Signals & Catalog" },
3527
+ { id: "delivery-history", label: "History & DLQ" }
3377
3528
  ]
3378
3529
  },
3379
3530
  {
@@ -4085,43 +4236,127 @@ function PlatformGuide({ LinkComponent }) {
4085
4236
  ] }),
4086
4237
  /* @__PURE__ */ jsx6(SubHeading, { id: "approval-gates", children: "Approval Gates" }),
4087
4238
  /* @__PURE__ */ jsx6(P, { children: "Threshold-based rules for auto-approving or flagging results. Configure per schema with criteria: minimum confidence, validation pass rate, field coverage. Results meeting all thresholds are auto-approved; others go to the manual review queue." }),
4088
- /* @__PURE__ */ jsx6(Callout, { children: "Approval gates integrate with exports \u2014 configure triggers to only push approved rows to your downstream systems." }),
4089
- /* @__PURE__ */ jsx6(SectionHeading, { id: "delivery", children: "Outputs" }),
4090
- /* @__PURE__ */ jsx6(P, { children: "Push reviewed and approved data to any downstream system." }),
4091
- /* @__PURE__ */ jsx6(SubHeading, { id: "destinations", children: "Destinations" }),
4239
+ /* @__PURE__ */ jsxs6(Callout, { children: [
4240
+ "Approval gates feed the delivery pipeline \u2014 bind a",
4241
+ " ",
4242
+ /* @__PURE__ */ jsx6(InlineCode, { children: "result.approved" }),
4243
+ " signal to a destination to only ship approved rows to your downstream systems."
4244
+ ] }),
4245
+ /* @__PURE__ */ jsx6(SectionHeading, { id: "delivery", children: "Delivery" }),
4246
+ /* @__PURE__ */ jsx6(P, { children: "Push extracted, resolved, and reviewed data to any downstream system. Delivery is a typed, at-least-once pipeline with idempotency keys on the wire, append-only history, and a dead-letter queue for terminal failures." }),
4247
+ /* @__PURE__ */ jsx6(SubHeading, { id: "delivery-pipeline", children: "How Delivery Works" }),
4248
+ /* @__PURE__ */ jsx6(P, { children: "Every delivery flows through a five-stage pipeline:" }),
4092
4249
  /* @__PURE__ */ jsx6(
4093
4250
  ParamTable,
4094
4251
  {
4095
- title: "Supported destination types",
4252
+ title: "The delivery pipeline",
4096
4253
  params: [
4097
- { name: "Webhook", type: "HTTP POST", description: "HMAC-SHA256 signed payloads to your endpoint." },
4098
- { name: "REST API", type: "HTTP", description: "Push to any REST endpoint with configurable headers." },
4099
- { name: "SFTP", type: "file", description: "Upload files to SFTP servers." },
4100
- { name: "Email", type: "attachment", description: "Send structured data as email attachments." },
4101
- { name: "S3 / R2", type: "object storage", description: "Push to cloud object storage (AWS S3 or Cloudflare R2)." }
4254
+ { name: "1. Signal", type: "event", description: "A producer emits a typed event (e.g. document.extracted, result.approved) into the outbox. Producers are stateless \u2014 they only publish." },
4255
+ { name: "2. Binding", type: "match", description: "A poller drains the outbox and matches each event against active bindings. A binding joins a signal filter to a deliverable + destination + serializer." },
4256
+ { name: "3. Resolver", type: "load", description: "The deliverable resolver loads the payload (document metadata, a record snapshot, an extraction run, \u2026) at delivery time using only entity IDs from the signal." },
4257
+ { name: "4. Serializer", type: "encode", description: "The serializer encodes the payload into the wire format \u2014 json, ndjson, csv, csv_file, xlsx, rows, graph, raw, md, or txt \u2014 after an optional field_map projection." },
4258
+ { name: "5. Connector", type: "transport", description: "The connector ships the encoded bytes through the TransportWrapper (SSRF guard, payload cap, rate limit, retry ladder). Slice-1 connector is webhook." }
4102
4259
  ]
4103
4260
  }
4104
4261
  ),
4105
- /* @__PURE__ */ jsx6(SubHeading, { id: "field-mappings", children: "Field Mappings" }),
4106
4262
  /* @__PURE__ */ jsxs6(P, { children: [
4107
- "Transform extraction output fields to match your destination's expected format. Configure source-to-destination field translation rules with value transformations. Manage from",
4263
+ "Every attempt is logged in ",
4264
+ /* @__PURE__ */ jsx6(InlineCode, { children: "delivery_items" }),
4265
+ ". Terminal failures (retry exhausted or permanent 4xx) write a ",
4266
+ /* @__PURE__ */ jsx6(InlineCode, { children: "delivery_dead_letter" }),
4108
4267
  " ",
4109
- /* @__PURE__ */ jsx6("strong", { children: "Outputs \u2192 Column Mappings" }),
4268
+ "row, which is replayable. The outbox, history, DLQ, and catalog are all accessible via the",
4269
+ " ",
4270
+ /* @__PURE__ */ jsxs6(LinkComp, { href: "/docs", className: "text-void-accent hover:underline", children: [
4271
+ /* @__PURE__ */ jsx6(InlineCode, { children: "/v1/delivery/*" }),
4272
+ " API"
4273
+ ] }),
4110
4274
  "."
4111
4275
  ] }),
4112
- /* @__PURE__ */ jsx6(SubHeading, { id: "export-triggers", children: "Triggers" }),
4276
+ /* @__PURE__ */ jsx6(SubHeading, { id: "destinations", children: "Destinations" }),
4277
+ /* @__PURE__ */ jsxs6(P, { children: [
4278
+ "A destination is a connector + configuration + optional credentials. Slice-1 ships the webhook connector; S3, Google Sheets, Drive, SFTP, and Email arrive in later slices. Use ",
4279
+ /* @__PURE__ */ jsx6("strong", { children: "Delivery \u2192 Destinations" }),
4280
+ " to manage them from the dashboard, or",
4281
+ " ",
4282
+ /* @__PURE__ */ jsx6(InlineCode, { children: "POST /v1/delivery/destinations" }),
4283
+ " via the API. Every destination supports a live-ping ",
4284
+ /* @__PURE__ */ jsx6(InlineCode, { children: "POST /v1/delivery/destinations/:id/test" }),
4285
+ " ",
4286
+ "that exercises the full transport envelope with a tiny test payload."
4287
+ ] }),
4113
4288
  /* @__PURE__ */ jsx6(
4114
4289
  ParamTable,
4115
4290
  {
4116
- title: "Trigger types",
4291
+ title: "Supported connectors",
4117
4292
  params: [
4118
- { name: "Auto on approval", type: "event", description: "Export immediately when rows are approved (stage or push mode)." },
4119
- { name: "Scheduled", type: "cron", description: "Export on a recurring cron schedule." },
4120
- { name: "Manual", type: "button", description: "Export on demand via button click." }
4293
+ { name: "webhook", type: "HTTP POST", description: "Slice 1. HMAC-SHA256 signed payloads with idempotency keys, 30s timeout, SSRF guard, 5 MiB payload cap (overridable per destination)." },
4294
+ { name: "s3", type: "object storage", description: "Slice 2+. AWS S3 or Cloudflare R2 with per-destination prefix and partitioning." },
4295
+ { name: "sheets", type: "api", description: "Slice 2+. Google Sheets append/upsert via connected accounts (OAuth)." },
4296
+ { name: "drive", type: "api", description: "Slice 2+. Google Drive file upload via connected accounts." },
4297
+ { name: "sftp", type: "file", description: "Slice 2+. SFTP file upload with key or password auth." },
4298
+ { name: "email", type: "smtp", description: "Slice 2+. Structured data as email attachment." }
4121
4299
  ]
4122
4300
  }
4123
4301
  ),
4124
- /* @__PURE__ */ jsx6(P, { children: "Every export is logged as a record with delivery status and error details. Failed exports retry automatically with exponential backoff." }),
4302
+ /* @__PURE__ */ jsx6(SubHeading, { id: "bindings", children: "Bindings" }),
4303
+ /* @__PURE__ */ jsxs6(P, { children: [
4304
+ "A binding is the routing rule: it joins a ",
4305
+ /* @__PURE__ */ jsx6("strong", { children: "signal filter" }),
4306
+ " (which events?) to a ",
4307
+ /* @__PURE__ */ jsx6("strong", { children: "deliverable type" }),
4308
+ " (what payload shape?) to a ",
4309
+ /* @__PURE__ */ jsx6("strong", { children: "destination" }),
4310
+ " ",
4311
+ "(ship where?) via a ",
4312
+ /* @__PURE__ */ jsx6("strong", { children: "serializer" }),
4313
+ " (encoded how?). On create, the backend validates all four pieces form a compatible triangle \u2014 the serializer must support the resolver's shape, and the connector must support the serializer format."
4314
+ ] }),
4315
+ /* @__PURE__ */ jsxs6(P, { children: [
4316
+ "Optional ",
4317
+ /* @__PURE__ */ jsx6(InlineCode, { children: "field_map" }),
4318
+ " (rename/drop/static rules) lets you reshape the payload without custom code. Optional ",
4319
+ /* @__PURE__ */ jsx6(InlineCode, { children: "delivery_policy" }),
4320
+ " ",
4321
+ "overrides the default retry ladder (6 attempts at",
4322
+ " ",
4323
+ /* @__PURE__ */ jsx6(InlineCode, { children: "5s, 30s, 2min, 10min, 1h" }),
4324
+ ") and timeout."
4325
+ ] }),
4326
+ /* @__PURE__ */ jsx6(SubHeading, { id: "signals-catalog", children: "Signals & Catalog" }),
4327
+ /* @__PURE__ */ jsxs6(P, { children: [
4328
+ "The catalog API (",
4329
+ /* @__PURE__ */ jsx6(InlineCode, { children: "/v1/delivery/catalog/*" }),
4330
+ ") exposes the four registries that drive the binding picker. Use it to populate dropdowns rather than hardcoding lists \u2014 it always reflects the running registry contents."
4331
+ ] }),
4332
+ /* @__PURE__ */ jsx6(
4333
+ ParamTable,
4334
+ {
4335
+ title: "Core signal types",
4336
+ params: [
4337
+ { name: "document.extracted", type: "signal", description: "Fired when a document completes extraction with structured fields." },
4338
+ { name: "document.extraction_failed", type: "signal", description: "Fired when extraction fails terminally." },
4339
+ { name: "run.dataspace.completed", type: "signal", description: "Fired when a dataspace job run completes." },
4340
+ { name: "run.structuring.completed", type: "signal", description: "Fired when a structuring run completes." },
4341
+ { name: "run.resolution.completed", type: "signal", description: "Fired when a resolution run (field normalization + transforms) completes." },
4342
+ { name: "run.extraction.completed", type: "signal", description: "Fired when a multi-document extraction (batch-inference) run completes." },
4343
+ { name: "result.approved", type: "signal", description: "Fired when a reviewer approves a record." },
4344
+ { name: "result.rejected", type: "signal", description: "Fired when a reviewer rejects a record." },
4345
+ { name: "result.flagged", type: "signal", description: "Fired when validation flags fire on a record." },
4346
+ { name: "delivery.item.completed", type: "meta", description: "Fired after a successful delivery. Meta-signal \u2014 the poller prevents re-binding loops." },
4347
+ { name: "delivery.item.failed", type: "meta", description: "Fired after a terminal delivery failure." }
4348
+ ]
4349
+ }
4350
+ ),
4351
+ /* @__PURE__ */ jsx6(SubHeading, { id: "delivery-history", children: "History & DLQ" }),
4352
+ /* @__PURE__ */ jsxs6(P, { children: [
4353
+ "Every delivery attempt writes a row to ",
4354
+ /* @__PURE__ */ jsx6(InlineCode, { children: "/v1/delivery/items" }),
4355
+ " with its status, HTTP code, error code, and request/response bodies. Terminal failures (retry ladder exhausted or permanent 4xx) escalate to",
4356
+ " ",
4357
+ /* @__PURE__ */ jsx6(InlineCode, { children: "/v1/delivery/dlq" }),
4358
+ ". Both are fully replayable \u2014 replay enqueues a new attempt with a fresh idempotency key. Nothing in history is ever mutated; the log is strictly append-only."
4359
+ ] }),
4125
4360
  /* @__PURE__ */ jsx6(SectionHeading, { id: "search-filtering", children: "Search & Filtering" }),
4126
4361
  /* @__PURE__ */ jsx6(SubHeading, { id: "omnisearch", children: "Omnisearch" }),
4127
4362
  /* @__PURE__ */ jsxs6(P, { children: [
@@ -4175,21 +4410,35 @@ function PlatformGuide({ LinkComponent }) {
4175
4410
  { name: "/v1/schemas", type: "CRUD", description: "Schema management \u2014 create, update, delete." },
4176
4411
  { name: "/v1/jobs", type: "CRUD", description: "Async job tracking and results." },
4177
4412
  { name: "/v1/sources", type: "CRUD", description: "API source management and document ingest." },
4178
- { name: "/v1/webhooks", type: "CRUD", description: "Webhook endpoint configuration." }
4413
+ { name: "/v1/delivery", type: "CRUD", description: "Outbound delivery: destinations, bindings, history, DLQ, outbox, catalog." }
4179
4414
  ]
4180
4415
  }
4181
4416
  ),
4182
4417
  /* @__PURE__ */ jsx6(SubHeading, { id: "webhooks", children: "Webhooks" }),
4183
4418
  /* @__PURE__ */ jsx6(P, { children: "Webhooks push real-time notifications when events occur. All payloads are HMAC-SHA256 signed. Failed deliveries retry with exponential backoff." }),
4419
+ /* @__PURE__ */ jsxs6(P, { children: [
4420
+ "The webhook connector is configured as a ",
4421
+ /* @__PURE__ */ jsx6("strong", { children: "delivery destination" }),
4422
+ ". Bind any of the signal types below to a webhook destination to receive real-time notifications. See ",
4423
+ /* @__PURE__ */ jsx6(InlineCode, { children: "/v1/delivery/catalog/signals" }),
4424
+ " for the exhaustive list."
4425
+ ] }),
4184
4426
  /* @__PURE__ */ jsx6(
4185
4427
  ParamTable,
4186
4428
  {
4187
- title: "Webhook event types",
4429
+ title: "Delivery signal types (webhook-compatible)",
4188
4430
  params: [
4189
- { name: "extraction.completed", type: "event", description: "A document extraction has finished." },
4190
- { name: "job.completed", type: "event", description: "An extraction job has completed all phases." },
4191
- { name: "export.completed", type: "event", description: "An export has been delivered." },
4192
- { name: "validation.completed", type: "event", description: "A validation run has finished." }
4431
+ { name: "document.extracted", type: "event", description: "A document extraction has finished successfully." },
4432
+ { name: "document.extraction_failed", type: "event", description: "A document extraction has failed terminally." },
4433
+ { name: "run.dataspace.completed", type: "event", description: "A dataspace job run completed." },
4434
+ { name: "run.structuring.completed", type: "event", description: "A structuring run completed." },
4435
+ { name: "run.resolution.completed", type: "event", description: "A resolution run (field normalization + transforms) completed." },
4436
+ { name: "run.extraction.completed", type: "event", description: "A multi-document extraction (batch-inference) run completed." },
4437
+ { name: "result.approved", type: "event", description: "A reviewer approved a record." },
4438
+ { name: "result.rejected", type: "event", description: "A reviewer rejected a record." },
4439
+ { name: "result.flagged", type: "event", description: "Validation flags fired on a record." },
4440
+ { name: "delivery.item.completed", type: "meta", description: "A delivery succeeded. Meta-signal \u2014 not re-delivered to avoid loops." },
4441
+ { name: "delivery.item.failed", type: "meta", description: "A delivery failed terminally." }
4193
4442
  ]
4194
4443
  }
4195
4444
  ),
@@ -4698,52 +4947,134 @@ var PLATFORM_FAQ = [
4698
4947
  ];
4699
4948
  var LLMS_TXT = `# Talonic
4700
4949
 
4701
- > Extract any document into schema-validated data with a single API call.
4950
+ > AI-powered document structuring platform that turns unstructured files into schema-validated, provenance-tracked structured data.
4702
4951
 
4703
- Talonic is an AI-powered document structuring platform. It ingests unstructured documents (PDFs, scans, images, spreadsheets), discovers fields through semantic clustering, and produces structured datasets with per-cell provenance, confidence scores, and reasoning traces.
4952
+ Talonic ingests documents in 25+ formats (PDFs, scans, images, spreadsheets, emails, archives), discovers every data field through AI extraction and semantic clustering, and produces structured datasets with per-cell confidence scores, reasoning traces, and source provenance. It runs a single deployable stack with Postgres + pgvector, Anthropic Claude for extraction, and Mistral Document AI for OCR.
4704
4953
 
4705
- ## Documentation
4954
+ ## How It Works
4706
4955
 
4707
- - [API Documentation](https://talonic.com/docs): Complete REST API reference
4708
- - [Platform Guide](https://talonic.com/docs/platform): Product documentation and feature guide
4709
- - [OpenAPI Spec](https://talonic.com/docs/openapi.json): Machine-readable API specification
4956
+ 1. **Upload** \u2014 Drag files/folders into Inputs or ingest via API. ZIP archives unpack automatically. Files are deduplicated via SHA-256 hashing.
4957
+ 2. **Extract** \u2014 Each document goes through Document AI OCR (converts to Markdown), classification against a 529-type ontology, and AI field extraction (discovers every data point with confidence and source text).
4958
+ 3. **Build Schema** \u2014 Extracted fields resolve into the Field Registry (canonical names, semantic clusters, master instructions). Define a user template selecting the fields you need.
4959
+ 4. **Run Job** \u2014 A 4-phase pipeline fills every cell in a documents \xD7 fields grid. ~30% filled instantly from graph matches, ~70% from AI agents.
4960
+ 5. **Deliver** \u2014 Push approved data to webhooks, REST APIs, SFTP, email, or S3/R2 cloud storage.
4710
4961
 
4711
- ## API Quick Start
4962
+ ## Sources & Documents
4712
4963
 
4713
- Base URL: https://api.talonic.com
4714
- Auth: Bearer token (tlnc_ prefix)
4964
+ Supported formats across three processing paths:
4965
+ - **Text fast-path** (direct read): TXT, MD, HTML, XML, JSON, EML, CSV
4966
+ - **AI Vision** (multimodal): PNG, JPG, JPEG, GIF, WEBP
4967
+ - **OCR** (Mistral Document AI \u2192 Markdown): PDF, DOCX, DOC, PPTX, PPT, XLSX, XLS, XLSM, MSG, BMP
4968
+ - **Archives**: ZIP (recursive unpack)
4715
4969
 
4716
- Extract a document:
4717
- \`\`\`
4718
- curl -X POST https://api.talonic.com/v1/extract \\
4719
- -H "Authorization: Bearer tlnc_sk_live_..." \\
4720
- -F "file=@document.pdf" \\
4721
- -F 'schema={"vendor_name":"string","total":"number"}'
4722
- \`\`\`
4970
+ Upload methods: drag-and-drop UI, folder upload (preserves file paths), API upload (single, batch up to 200 files, or archive up to 500 MB). Batch mode available at 50% cost with 48-hour delivery window.
4971
+
4972
+ Every document is classified into a canonical type from the 529-type ontology (e.g., "Employment Contract", "Invoice", "Bill of Lading"). Classification is language-agnostic \u2014 a German Arbeitsvertrag maps to the same type as an English Employment Contract. Unresolvable documents get "Unclassified Document".
4973
+
4974
+ Document detail tabs: Raw Extraction (every field with confidence), Resolved Data (mapped to registry), Processing Log (per-stage timing), Original File.
4975
+
4976
+ ## Field Registry
4977
+
4978
+ The unified knowledge graph of all canonical fields, growing smarter with every document processed.
4979
+
4980
+ - **Tier 1 (Core)**: Universal fields across many document types. Most reliable.
4981
+ - **Tier 2 (Established)**: Promoted from Tier 3 after frequency thresholds. Production-ready.
4982
+ - **Tier 3 (Emerging)**: Newly discovered from a few documents. May promote as more data arrives.
4983
+
4984
+ Fields with similar meanings cluster automatically via AI embeddings (e.g., "Vendor Name", "Supplier Name", "Company Name" \u2192 same cluster). Master instructions are AI-synthesized extraction directives that improve accuracy over time.
4985
+
4986
+ ## Schemas
4987
+
4988
+ Two types: **Generated schemas** (auto-created per document type from Tier 1+2 fields) and **User templates** (user-defined output structures).
4989
+
4990
+ Template workflow: name it \u2192 add fields (display name, data type, extraction instructions) \u2192 map to registry (exact/semantic/composite matching) \u2192 add reference tables \u2192 publish an immutable version.
4723
4991
 
4724
- ## Key Endpoints
4992
+ Field features: format constraints (regex validation with empty/flag/constant fallback), modifiers (date/number format, alias mapping, max_length), bypass strategies (constant, generator, reference lookup \u2014 skip LLM), capture submoves (match \u2192 compute \u2192 reason), output name remapping.
4725
4993
 
4726
- - POST /v1/extract \u2014 Extract structured data from a document
4727
- - GET /v1/documents \u2014 List and manage documents
4728
- - GET /v1/extractions \u2014 Query extraction results
4729
- - POST /v1/schemas \u2014 Create reusable extraction schemas
4730
- - GET /v1/jobs \u2014 Track async extraction jobs
4731
- - POST /v1/sources \u2014 Manage document sources with API keys
4994
+ Versioning: Live (published, read-only), Workshop (mutable draft), Version History (timeline with diff). Test extraction compares draft vs. live results before publishing.
4732
4995
 
4733
- ## Platform Features
4996
+ ## Extraction Jobs (Runs)
4734
4997
 
4735
- - 25+ file format support (PDF, DOCX, images, spreadsheets, archives)
4736
- - Field Registry: unified knowledge graph of canonical fields with tier system
4737
- - 4-phase extraction pipeline: Resolve \u2192 Agent \u2192 Validate \u2192 Re-read
4738
- - Document linking and case discovery through shared entities
4739
- - Validation checks, golden samples, and approval gates
4740
- - Export to webhooks, REST APIs, SFTP, email, cloud storage
4741
- - HMAC-SHA256 signed webhooks with retry policy
4998
+ A job applies a schema to documents, producing a grid (rows = documents, columns = fields). Navigate to Structuring \u2192 Runs \u2192 New.
4742
4999
 
4743
- ## Optional
5000
+ **4-phase pipeline:**
5001
+ 1. **Resolve** \u2014 ~30% of cells in seconds. Graph matches, fuzzy name matching, concept-synonym expansion, 3-tier reference lookup (normalize \u2192 fuzzy \u2192 AI), description scan. No AI calls (except rare Haiku fallback). Values normalized: dates \u2192 YYYY/MM/DD, numbers \u2192 2 decimal places.
5002
+ 2. **Agent** \u2014 AI reviews gap patterns and produces typed strategy per field: compute (formula from grid values), transfer (copy from equivalent field), extract (re-read document with instructions, 5 concurrent), skip (with reasoning). Fields with manual instructions are always extracted, never skipped.
5003
+ 3. **Validation** \u2014 Cross-field sanity checks: date_sanity, amount_mismatch, lookup_failed, low_confidence_outlier, unexpected_empty. Flags are informational only \u2014 never block output.
5004
+ 4. **Re-read** \u2014 Context-aware gap filling. For each empty/low-confidence cell, AI re-reads the original document with field instruction + full grid context. Respects the confidence gate: cells \u2265 0.7 confidence are permanently protected.
4744
5005
 
4745
- - [API Documentation (Markdown)](https://talonic.com/docs/api.md)
4746
- - [Platform Guide (Markdown)](https://talonic.com/docs/platform.md)
5006
+ Per-cell provenance: confidence (0.0\u20131.0), resolution_type (graph_match | agent_derived | source_reread | unresolved), phase (1\u20134), reasoning trace, source reference (document, page, field).
5007
+
5008
+ ## Cases & Document Linking
5009
+
5010
+ Registry fields can be link keys: Identity (company/person names), Transaction (contract/PO/invoice numbers), Reference (project codes, cost centers). The linking pipeline normalizes values and builds a bipartite graph of documents \u2194 entities.
5011
+
5012
+ A **case** = 2+ documents connected through transaction/reference entities. An **entity group** = 2+ documents connected through identity-only entities. High-frequency entities (>30% of documents) are auto-excluded from case formation.
5013
+
5014
+ Case detail: documents, shared entities, evidence chain, timeline, AI-generated narration. Document Graph provides a D3-force visual layout. Case templates auto-discovered after 3+ cases form.
5015
+
5016
+ ## Smart Matching
5017
+
5018
+ Upload CSV/Excel as reference datasets. Define field-to-field comparisons with weighted strategies: exact (case-insensitive), fuzzy (token-based with similarity threshold), date_range (configurable tolerance), numeric_range (percentage or absolute tolerance). AI can auto-suggest field mappings.
5019
+
5020
+ Results: top 5 candidates per document with confidence scores and per-field evidence breakdown.
5021
+
5022
+ ## Validation & Quality
5023
+
5024
+ - **Validation checks**: Schema-level rules (field format, value range, cross-field consistency, AI-proposed coherence). Run during Phase 3.
5025
+ - **Golden samples**: Manually-created reference datasets. Benchmark runs compare extraction vs. golden for per-field accuracy with AI judge verdicts.
5026
+ - **Approval gates**: Threshold-based auto-approve/flag (minimum confidence, validation pass rate, field coverage). Failed rows go to manual review queue.
5027
+
5028
+ ## Delivery
5029
+
5030
+ Destinations: Webhook (HMAC-SHA256 signed), REST API (configurable headers), SFTP, Email (attachments), S3/R2 (cloud storage).
5031
+
5032
+ Field mappings transform output fields to match destination format. Triggers: auto on approval (stage/push), scheduled (cron), or manual. Failed exports retry with exponential backoff.
5033
+
5034
+ Dialects control serialization: date_format, number_locale, CSV delimiter, null representation, boolean format, encoding (UTF-8, UTF-8-BOM, ISO-8859-1).
5035
+
5036
+ ## Search & Navigation
5037
+
5038
+ **Omnisearch** (Cmd+K / Ctrl+K): searches across documents, extracted values, field names, schema names, and sources simultaneously.
5039
+
5040
+ Document filters: field-value conditions with autocomplete, comparison operators (eq, contains, gt, between, is_empty), combinable. URL-serializable and saveable as presets.
5041
+
5042
+ Keyboard shortcuts: Cmd+K (search), Cmd+J (quick extract), Escape (close overlays).
5043
+
5044
+ ## Team & Settings
5045
+
5046
+ 4 roles: Viewer (read-only), Member (full CRUD), Admin (+ team management), Owner (+ billing, API keys, org settings). New members auto-match by email domain with pending approval.
5047
+
5048
+ Usage & Registry: per-feature cost breakdown, daily cost chart, call log with model/tokens/cost. Admin master view for cross-tenant stats.
5049
+
5050
+ ## API
5051
+
5052
+ Base URL: \`https://api.talonic.com\`. Auth: \`Authorization: Bearer tlnc_...\` (SHA-256 hashed, shown once at creation). Scopes: extract, read, write.
5053
+
5054
+ Key endpoints:
5055
+ - POST /v1/extract \u2014 Synchronous/async document extraction (\`include_markdown=true\` returns OCR text, \`processing_mode=batch\` for 50% cost)
5056
+ - GET /v1/documents \u2014 List with cursor pagination; GET /v1/documents/:id/markdown for OCR text
5057
+ - GET /v1/extractions \u2014 Query results and field corrections
5058
+ - POST /v1/schemas \u2014 Create/manage extraction schemas
5059
+ - GET /v1/jobs \u2014 Track async jobs and results
5060
+ - POST /v1/sources \u2014 Manage API sources and document ingest
5061
+ - POST /v1/webhooks \u2014 Configure webhook endpoints
5062
+
5063
+ Webhook events: extraction.completed, job.completed, export.completed, validation.completed. All HMAC-SHA256 signed with retry on failure.
5064
+
5065
+ ## Agent
5066
+
5067
+ The embedded AI assistant accessible from any page. Two modes:
5068
+ - **Chat mode** \u2014 Ask questions about the platform, your documents, extraction results, schemas, or workflows. Grounded in platform documentation.
5069
+ - **Planning mode** \u2014 Request actions (create schemas, run jobs, configure exports). The agent builds a plan, confirms with you, then executes.
5070
+
5071
+ Document upload flow: Cmd+J or the upload button opens quick extract. Drop a file, select a schema (or let AI discover fields), and get structured results.
5072
+
5073
+ ## Documentation
5074
+
5075
+ - [API Documentation](https://talonic.com/docs): Complete REST API reference
5076
+ - [Platform Guide](https://talonic.com/docs/platform): Product documentation and feature guide
5077
+ - [OpenAPI Spec](https://talonic.com/docs/openapi.json): Machine-readable API specification
4747
5078
  `;
4748
5079
  var LLMS_FULL_TXT_HEADER = `# Talonic \u2014 Full Documentation
4749
5080