Overview
By default, OkraPDF routes all chat completions through OpenRouter. If you’d rather call Anthropic, OpenAI, or Google directly — for cost control, latency, or compliance — you can pass your own API key.
Two ways to provide keys:
| Method | Persistence | Best for |
|---|
X-Vendor-Keys header | Per-request (ephemeral) | Scripts, CI, testing |
| Settings > API Keys > Vendor Keys | Encrypted at rest (AES-GCM) | Production apps |
Your key is never logged, never included in prompts, and never stored unless you explicitly save it to the vault.
Quick example (curl)
curl -X POST https://api.okrapdf.com/document/doc-abc123/chat/completions \
-H "Authorization: Bearer okra_YOUR_KEY" \
-H "Content-Type: application/json" \
-H 'X-Vendor-Keys: {"openai": "sk-proj-..."}' \
-d '{
"messages": [{"role": "user", "content": "What was total revenue?"}],
"agentConfigOverride": {
"llm": {"chat": {"provider": "openai", "model": "gpt-4o-mini"}}
}
}'
The request hits api.openai.com/v1 directly. OpenRouter is not involved.
Supported providers
| Provider | provider value | Example model | Base URL |
|---|
| OpenRouter | openrouter | anthropic/claude-haiku-4.5 | openrouter.ai/api/v1 |
| Anthropic | anthropic | claude-haiku-4-5-20251001 | api.anthropic.com |
| OpenAI | openai | gpt-4o, gpt-4o-mini | api.openai.com/v1 |
| Google | google | gemini-2.5-flash | generativelanguage.googleapis.com |
SDK usage
import { createOkra } from '@okrapdf/runtime';
const okra = createOkra({ apiKey: process.env.OKRA_API_KEY });
const session = okra.sessions.from('doc-abc123');
const { answer } = await session.prompt('Summarize the risk factors', {
vendorKeys: { openai: process.env.OPENAI_API_KEY },
agentConfigOverride: {
llm: { chat: { provider: 'openai', model: 'gpt-4o-mini' } },
},
});
MCP usage (Claude Desktop / Claude Code)
In MCP tools like ask_document and extract_data, use the provider:model colon format:
> Ask doc-abc123 "What was total revenue?" using openai:gpt-4o-mini
The colon tells OkraPDF to route directly. A slash (anthropic/claude-haiku-4.5) routes through OpenRouter.
| Format | Route |
|---|
openai:gpt-4o | Direct to OpenAI |
anthropic:claude-haiku-4-5-20251001 | Direct to Anthropic |
google:gemini-2.5-flash | Direct to Google |
anthropic/claude-haiku-4.5 | Via OpenRouter |
For MCP, store your vendor key in Settings > API Keys > Vendor Keys so it persists across requests. The MCP transport doesn’t support custom headers.
Storing keys in the vault
Go to okrapdf.com/settings/api-keys and add your vendor key under the appropriate namespace (openai, anthropic, or google). Keys are encrypted with AES-GCM and only decrypted at call time.
Once stored, you don’t need X-Vendor-Keys — OkraPDF resolves your key automatically when provider is set.
Key resolution order
When a completion request specifies a provider, OkraPDF resolves the API key in this order:
X-Vendor-Keys header (per-request override)
- Vault lookup by secret namespace
- Resolved secrets overlay (internal)
- Worker environment variable (platform default)
The first match wins. This means X-Vendor-Keys always takes priority.
Security
- In transit: All requests use HTTPS/TLS
- At rest: Vault keys encrypted with AES-GCM (KEK stored as CF Worker secret)
- Ephemeral keys (
X-Vendor-Keys): held in Worker memory for the request duration, never persisted
- No logging: Key values are never written to logs, SQLite, or R2
- Scoped forwarding: Your key is only sent to the provider you specified — never to third parties