Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a0e0f73
refactor(dashboard): simplify onboarding layout
urjitc Jul 21, 2026
3a9a2ad
feat(api-keys): allow unnamed keys
urjitc Jul 21, 2026
c9b7ab0
docs: document the tech stack
urjitc Jul 21, 2026
cd821b2
feat(sdk): add hosted native parser providers
urjitc Jul 21, 2026
adccf19
feat(hosted): run native parsers in private containers
urjitc Jul 21, 2026
b80097b
docs: explain hosted native parser execution
urjitc Jul 21, 2026
4e13823
fix(brand): refine logo geometry
urjitc Jul 21, 2026
bb5ec0d
docs(mintlify): simplify docs navigation
urjitc Jul 21, 2026
5f75393
feat(sdk): report provider execution costs
urjitc Jul 21, 2026
27d9a40
feat(platform): add metering and observability
urjitc Jul 21, 2026
ae11730
fix(workflows): reconcile ambiguous job startup
urjitc Jul 21, 2026
65a7c5d
fix(workflows): retry recoverable workflow steps
urjitc Jul 21, 2026
6804d6f
feat(sdk): expose recoverable hosted jobs
urjitc Jul 21, 2026
824d33e
refactor(validation): centralize record guards
urjitc Jul 21, 2026
00cd6cb
fix(sdk): harden hosted job recovery
urjitc Jul 22, 2026
84dec3c
fix(native-parsers): harden hosted execution boundaries
urjitc Jul 22, 2026
b4e62a8
feat(billing): add hosted credits and checkout
urjitc Jul 22, 2026
ace3877
fix(workflows): enforce hosted credit lifecycle
urjitc Jul 22, 2026
2a64aa3
refactor(observability): remove PostHog pass-through
urjitc Jul 22, 2026
5b3e420
feat(marketing): clarify hosted pricing and routing
urjitc Jul 22, 2026
7fce6af
docs: explain hosted credit usage
urjitc Jul 22, 2026
97f7c75
feat(dashboard): explain hosted credits
urjitc Jul 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .dev.vars.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,11 @@ BETTER_AUTH_URL="http://localhost:3000"
# LLAMA_CLOUD_API_KEY=""
# MISTRAL_API_KEY=""
# DATALAB_API_KEY=""

# Autumn usage metering. Use a sandbox key for local development.
# AUTUMN_SECRET_KEY="am_sk_test_..."

# Optional product analytics and error tracking. The project token is public;
# leave it unset to disable PostHog without changing application behavior.
# POSTHOG_PROJECT_TOKEN=""
# POSTHOG_HOST="https://us.i.posthog.com"
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,14 @@ npx @file_router/cli@latest parse report.pdf
| | Hosted API | Direct with your keys |
| --------------------- | -------------------------------------- | -------------------------------------- |
| Best for | The fastest setup | Keeping provider calls in your runtime |
| Authentication | One FileRouter API key | Your provider API keys |
| Authentication | A FileRouter API key | Your provider API keys |
| Document sent through | FileRouter, then the selected provider | The selected provider only |
| Billing | FileRouter credits | Provider billing |
| TypeScript | `FileRouterClient` | `FileRouter` |
| CLI | Default after `filerouter login` | Add `--local` |

Credits pay for hosted processing. Each account receives 5,000 free credits each month, purchased credits never expire, and direct requests do not use FileRouter credits.

Direct TypeScript example:

```ts
Expand All @@ -103,9 +106,24 @@ const result = await router.parse("./report.pdf", {
- **LlamaParse** for layout-aware document parsing.
- **Mistral OCR** for OCR with structured document output.
- **Datalab** for document conversion and extraction.
- **LiteParse** for open-source parsing with optional OCR, screenshots, and
Office conversion.
- **PDF Inspector** for fast PDF classification and text-layer inspection.

More adapters are coming.

<details>
<summary><strong>Tech stack</strong></summary>

- **App:** TypeScript, React 19, TanStack Start, Router, and Query.
- **API and auth:** Hono with OpenAPI and Zod, plus Better Auth.
- **Durable backend:** Cloudflare Workers and Workflows, with D1 through
Drizzle ORM and R2 for documents and results.
- **SDK and CLI:** A pnpm workspace with provider-neutral TypeScript packages.
- **UI and tooling:** Tailwind CSS 4, Radix UI, Vite+, and Vitest.

</details>

## Development

FileRouter requires Node.js 22.14 or newer.
Expand Down
2 changes: 2 additions & 0 deletions docs/api/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ API errors use `application/problem+json` and include a stable code, HTTP status
"request_id": "..."
}
```

A `402 Payment Required` response with code `insufficient_credits` means the account is out of credits. Add credits from the [dashboard](https://filerouter.dev/dashboard) before retrying the request. See [How credits work](/concepts/processing-modes#how-credits-work) for pricing details.
2 changes: 1 addition & 1 deletion docs/assets/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/assets/filerouter-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions docs/assets/filerouter-wordmark-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions docs/assets/filerouter-wordmark-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/cli/overview.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "CLI"
sidebarTitle: "Overview"
description: "Parse and compare documents from the terminal."
---

Expand Down
8 changes: 6 additions & 2 deletions docs/concepts/how-it-works.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ Processes a document with one provider and returns a `ParseResult`.

Processes the same resolved document across several providers concurrently. The returned `CompareResult` retains a status and duration for every provider, including failures and unsupported output combinations.

## Built-in adapters
## Built-in providers

The SDK currently includes adapters for `llamaparse`, `mistral-ocr`, and `datalab`. Each adapter advertises its supported outputs and execution model through the provider catalog.
Hosted jobs can select `llamaparse`, `mistral-ocr`, `datalab`, `liteparse`, or
`pdf-inspector`. LiteParse and PDF Inspector run in separate private parser
pools so lightweight PDF inspection does not inherit the OCR and Office
conversion footprint. Every provider advertises its supported outputs and
execution model through its runtime adapter.
16 changes: 16 additions & 0 deletions docs/concepts/processing-modes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,30 @@ FileRouter supports two explicit processing modes. Neither mode silently falls b
| Authentication | FileRouter API key | Provider API keys |
| Document route | Your app → FileRouter → provider | Your app → provider |
| Job orchestration | Managed by FileRouter | Runs in your process |
| Billing | FileRouter credits | Provider billing |
| CLI | Default after `login` | Add `--local` |

## Hosted

Hosted processing is the shortest path to production. FileRouter accepts the input, creates a durable job, submits it to the selected provider, polls long-running provider jobs, stores the result, and cleans up uploaded source documents after the job reaches a terminal state.

Credits pay for FileRouter-hosted processing. Each account receives **5,000 free credits each month**, and purchased credits never expire. Direct or BYOK requests do not use FileRouter credits.

## How credits work

**1,000 credits equal $1 of FileRouter-hosted usage.** Credit usage is based on the selected parser's upstream price and the infrastructure needed to run the job, with a 10% FileRouter beta margin included. Native parser usage depends on active processing time and allocated compute.

A comparison uses credits for each provider that successfully returns a parsed result. Providers that fail before returning a result do not consume credits. Direct or BYOK requests are billed by the provider and never use FileRouter credits.

Free credits reset each month. Purchased credits never expire and remain available after the monthly allowance resets.

Hosted binary uploads are limited to **100 MB**. Completed results expire after **7 days**, and job records are retained for **30 days**.

Public URL inputs are fetched once into temporary FileRouter storage before any
provider runs. This gives comparisons one immutable source and avoids sending a
user-controlled URL to private native parsers. Source objects are deleted when
the job reaches a terminal state.

## Direct / BYOK

Direct processing uses provider adapters from `@file_router/sdk` inside your runtime. Your document and provider credential do not pass through FileRouter, but the selected provider still receives the document.
Expand Down
73 changes: 34 additions & 39 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@
"$schema": "https://mintlify.com/docs.json",
"name": "FileRouter",
"description": "Durable document parsing across providers.",
"theme": "luma",
"theme": "mint",
"logo": {
"light": "/assets/filerouter-logo.svg",
"dark": "/assets/filerouter-logo.svg",
"light": "/assets/filerouter-wordmark-light.svg",
"dark": "/assets/filerouter-wordmark-dark.svg",
"href": "https://filerouter.dev"
},
"favicon": "/assets/favicon.svg",
"appearance": {
"default": "system"
},
"fonts": {
"family": "Geist"
},
"colors": {
"primary": "#00bdf7",
"light": "#00bdf7",
Expand All @@ -22,13 +28,12 @@
{
"label": "GitHub",
"href": "https://github.com/ThinkEx-OSS/filerouter"
},
{
"label": "Dashboard",
"href": "https://filerouter.dev/dashboard"
}
],
"primary": {
"type": "button",
"label": "Dashboard",
"href": "https://filerouter.dev/dashboard"
}
]
},
"footer": {
"socials": {
Expand All @@ -37,40 +42,30 @@
}
},
"navigation": {
"tabs": [
"groups": [
{
"tab": "Documentation",
"groups": [
{
"group": "Start",
"pages": ["index", "quickstart"]
},
{
"group": "Concepts",
"pages": [
"concepts/how-it-works",
"concepts/processing-modes",
"concepts/results"
]
},
{
"group": "TypeScript SDK",
"pages": ["sdk/parse", "sdk/compare", "sdk/provider-options"]
},
{
"group": "CLI",
"pages": ["cli/overview"]
}
]
"group": "Get started",
"pages": ["index", "quickstart"]
},
{
"tab": "API Reference",
"groups": [
{
"group": "Hosted API",
"pages": ["api/overview", "api/jobs"]
}
"group": "Concepts",
"pages": [
"concepts/how-it-works",
"concepts/processing-modes",
"concepts/results"
]
},
{
"group": "TypeScript SDK",
"pages": ["sdk/parse", "sdk/compare", "sdk/provider-options"]
},
{
"group": "Command line",
"pages": ["cli/overview"]
},
{
"group": "API reference",
"pages": ["api/overview", "api/jobs"]
}
]
}
Expand Down
7 changes: 3 additions & 4 deletions docs/index.mdx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
---
title: "FileRouter"
title: "One API for document parsing"
sidebarTitle: "Overview"
description: "Durable document parsing across providers through one API."
---

# One API for document parsing

FileRouter gives your application one contract for sending documents to parsing providers. Start with one provider, compare outputs when you need to, and keep provider-specific uploads, async jobs, and result shapes out of your application code.

<CardGroup cols={2}>
Expand Down Expand Up @@ -32,7 +31,7 @@ FileRouter gives your application one contract for sending documents to parsing
- Provider submission and polling for long-running jobs
- Consistent page numbers, outputs, timing, warnings, and errors
- Side-by-side provider comparisons that preserve individual failures
- Hosted processing with one FileRouter key or direct processing with your provider keys
- Hosted processing with a FileRouter API key or direct processing with your provider keys

<Note>
FileRouter standardizes the workflow around document parsers. Provider
Expand Down
8 changes: 8 additions & 0 deletions docs/sdk/provider-options.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Each provider reads only its own namespace:
- `providerOptions.llamaparse`
- `providerOptions["mistral-ocr"]`
- `providerOptions.datalab`
- `providerOptions.liteparse`
- `providerOptions["pdf-inspector"]`

This keeps native settings available without flattening incompatible provider APIs into one shared object.

Expand All @@ -32,3 +34,9 @@ This keeps native settings available without flattening incompatible provider AP
</Note>

Hosted requests encode provider options as JSON. The encoded options are limited to **64 KiB**.

Hosted LiteParse supports curated options for managed OCR, Office conversion,
image handling, complexity analysis, and screenshots. Transport credentials,
custom OCR server URLs, passwords, and filesystem paths are rejected. FileRouter
never silently disables a requested capability; unsupported options fail the
job explicitly.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"db:migrate": "wrangler d1 migrations apply DB --remote",
"db:check": "drizzle-kit check",
"r2:lifecycle": "wrangler r2 bucket lifecycle set filerouter-files --file infra/r2-lifecycle.json --force",
"test": "vp test run --passWithNoTests && pnpm test:worker && pnpm --filter @file_router/sdk test && pnpm --filter @file_router/cli test",
"test": "vp test run --passWithNoTests && pnpm test:worker && pnpm --filter @file_router/sdk test && pnpm --filter @file_router/cli test && pnpm --filter @file_router/native-parsers test",
"test:worker": "vitest run --config vitest.worker.config.ts",
"lint": "vp lint",
"format": "vp fmt",
Expand All @@ -43,12 +43,15 @@
"@tanstack/react-router-devtools": "1.167.0",
"@tanstack/react-router-ssr-query": "1.167.1",
"@tanstack/react-start": "1.168.30",
"autumn-js": "1.2.43",
"better-auth": "^1.6.23",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"drizzle-orm": "^0.45.2",
"hast-util-to-string": "^3.0.1",
"hono": "^4.12.31",
"posthog-js": "1.404.1",
"posthog-node": "5.45.2",
"prism-react-renderer": "^2.4.1",
"radix-ui": "^1.6.1",
"react": "^19.2.6",
Expand Down
Loading