Unify your external services
Every API behind one stable URL. hodor injects the credentials; your keys never leave your server.
One URL per service
openai.example.com is an integration. Subdomain routing — no path config, nothing to remember.
Credentials handled
Store the key once, encrypted. hodor builds the auth header at request time — callers never see a credential.
Plain HTTP in and out
curl, scripts, agents, browsers. If it speaks HTTPS it works. No SDK, no protocol, no MCP.
Four services, four credentials, four leak surfaces — vs the same four calls with one hodor key and nothing else. Same curl, same JSON, same responses; the URL changed and the keys left the room.
curl -X POST https://api.linear.app/graphql \
-H "Authorization: lin_api_xxxx" \
-d '{"query":"{ viewer { name } }"}'
curl -H "Authorization: Bearer phx_xxxx" \
https://eu.posthog.com/api/projects/213853/feature_flags/
curl -H "Authorization: Bearer cfat_xxxx" \
https://api.cloudflare.com/client/v4/user/tokens/verify
curl -H "Authorization: Bearer xa-xxxx" \
https://api.axiom.co/v1/datasets
curl -X POST https://linear.example.com/graphql \
-H "X-Authorization: Bearer $HODOR_KEY" \
-d '{"query":"{ viewer { name } }"}'
curl -H "X-Authorization: Bearer $HODOR_KEY" \
https://posthog.example.com/api/projects/213853/feature_flags/
curl -H "X-Authorization: Bearer $HODOR_KEY" \
https://cloudflare.example.com/user/tokens/verify
curl -H "X-Authorization: Bearer $HODOR_KEY" \
https://axiom.example.com/v1/datasets
The four upstream credentials stay encrypted on your server — no caller ever holds one. Each caller (agent, cron, script) gets its own hodor key, minted with the finest grain you want: read-only vs write, restricted to specific integrations, restricted to specific paths, revocable in ~30 seconds. Rotating a service key upstream is one admin call, not a hunt through every tool that ever touched it.
One worker, two secrets, one DNS record. No installer, no lock-in — it's ordinary Cloudflare Workers (or a plain Node/Bun process).
Local dev first:
git clone git@github.com:butttons/hodor.git && cd hodor
pnpm install
cp apps/proxy-worker/.dev.vars.example apps/proxy-worker/.dev.vars # fill the two keys
pnpm --filter @hodor/proxy-worker dev # → localhost:8787
Deploy: create the HODOR_KV namespace, add a proxied DNS
record (*.example.com → 192.0.2.0), then
npx wrangler deploy --secrets-file .dev.vars for the
first deploy (uploads the two required secrets); later deploys are
plain wrangler deploy. Full steps in
llms.txt.
Configure once through a small admin API — no code, no redeploys. Three calls, one-time setup:
Store the key
Encrypted at rest; hodor is the only reader.
curl -X PUT -H "X-Authorization: Bearer $TOKEN" \
--data-binary 'sk-...' \
https://example.com/_/admin/secrets/OPENAI_API_KEY
Register the integration
The full payload — target, the JEXL header that resolves the secret at request time, and an optional probe.
curl -X PATCH https://example.com/_/admin/registry/openai \
-H "X-Authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
--data-binary @- <<'JSON'
{
"id": "openai",
"description": "OpenAI REST API",
"url": { "host": "api.openai.com", "path": "/v1" },
"headers": { "Authorization": "'Bearer ' + kv('OPENAI_API_KEY')" },
"probe": { "method": "GET", "path": "/v1/models" }
}
JSON
Call it
Credentials injected for you, upstream.
curl https://openai.example.com/v1/models
One signed JWT per consumer. Restrictions use a single vocabulary — only / except — globally and per integration. except always wins; per-item rules narrow the globals, never widen.
{
"scopes": ["proxy:call"],
"integrations": [
{"id": "stripe"},
{"id": "razorpay", "only": {"methods": ["GET", "HEAD"]}}
]
}
Stripe stays broad, Razorpay is read-only — on the same key. Mint at POST /_/keys, revoke one key without touching the rest, and read every integration in the catalog.
- Free tier works out of the box. The proxy runs at
*.example.com(first level), which Cloudflare's free Universal SSL covers — apex and first level need zero certificate setup. - Deeper subdomains (
a.b.example.com) are a TLS thing, not a DNS thing — DNS routes at any depth, certificates don't. Those need Total TLS (paid) or a custom certificate (Business plan).
- Keys stay encrypted. Credentials are AES-GCM ciphertext in KV; only hodor can decrypt them, and only at request time.
- Scoped, revocable access. Each consumer gets its own signed key. Revoke one in ~30 seconds, or rotate the signing secret to void everything at once.
- Complete audit log. Every request is recorded — who called which integration, when, and what came back — including rejections and upstream failures.
hodor