everyapp 0.2.2 → 0.3.0-rc.2
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/LICENSE +21 -0
- package/README.md +6 -77
- package/bin/everyapp.js +235 -0
- package/dist/access-LGEN3ABJ.js +1 -0
- package/dist/activity-RSD4D66F.js +12 -0
- package/dist/apps-4RCFXT74.js +13 -0
- package/dist/chunk-23HJ5I2A.js +2 -0
- package/dist/chunk-2Y5Q6A5K.js +6 -0
- package/dist/chunk-4JRIS6S6.js +1 -0
- package/dist/chunk-5PTNYZK6.js +4 -0
- package/dist/chunk-6OGVO7QK.js +6 -0
- package/dist/chunk-6PGUCTJ6.js +11 -0
- package/dist/chunk-AGTCKFRB.js +22 -0
- package/dist/chunk-BHMRY53V.js +2 -0
- package/dist/chunk-CB4U7H2G.js +4 -0
- package/dist/chunk-CCWBPAKH.js +4 -0
- package/dist/chunk-CZTEDWZ2.js +22 -0
- package/dist/chunk-CZXHKPRZ.js +2 -0
- package/dist/chunk-E3EPK27P.js +10 -0
- package/dist/chunk-EGEWRFVY.js +1 -0
- package/dist/chunk-ELK7QZ2M.js +1 -0
- package/dist/chunk-FJJSSVET.js +33 -0
- package/dist/chunk-GKBPYVP3.js +25 -0
- package/dist/chunk-H6QQMY7B.js +18 -0
- package/dist/chunk-H7PDL3X5.js +1 -0
- package/dist/chunk-HOUHG236.js +20 -0
- package/dist/chunk-IFCPALVC.js +46 -0
- package/dist/chunk-IUOBIB5M.js +30 -0
- package/dist/chunk-J35DDCNU.js +1 -0
- package/dist/chunk-J455FAEN.js +7 -0
- package/dist/chunk-JYKRUS5C.js +1 -0
- package/dist/chunk-LXYMDZER.js +1 -0
- package/dist/chunk-LYNBZ7RV.js +57 -0
- package/dist/chunk-M2QQ2UD7.js +132 -0
- package/dist/chunk-N4E5YE4X.js +5 -0
- package/dist/chunk-N5GQLGEC.js +2 -0
- package/dist/chunk-NFU4YFXB.js +1 -0
- package/dist/chunk-OM2HDWVP.js +1 -0
- package/dist/chunk-ONLNJXVQ.js +32 -0
- package/dist/chunk-OP4DYXYI.js +2 -0
- package/dist/chunk-PNLU5U3P.js +1 -0
- package/dist/chunk-PS7S74DG.js +6 -0
- package/dist/chunk-RMF4YGD6.js +98 -0
- package/dist/chunk-T2GD7RHS.js +10 -0
- package/dist/chunk-TLRM3P7V.js +15 -0
- package/dist/chunk-W3JCQHHU.js +1 -0
- package/dist/chunk-WOVS3GV5.js +10 -0
- package/dist/chunk-YHJZMJYZ.js +1 -0
- package/dist/chunk-ZECBN24L.js +15 -0
- package/dist/chunk-ZEXVHB22.js +2 -0
- package/dist/chunk-ZFCUH5PK.js +7 -0
- package/dist/configure-F7UZCJUG.js +8 -0
- package/dist/create-2E5HVWYK.js +22 -0
- package/dist/db-HEQVTDTM.js +9 -0
- package/dist/delete-XCSIQIRS.js +3 -0
- package/dist/deploy-3QOZEZHC.js +1 -0
- package/dist/dev-JL3ZP5BT.js +86 -0
- package/dist/email-RLZFUFUN.js +10 -0
- package/dist/events-2V5VRBWP.js +15 -0
- package/dist/groups-HDG5DVFY.js +8 -0
- package/dist/index.js +97 -1
- package/dist/install-Z5FYXUYM.js +1 -0
- package/dist/login-KHJBC64Z.js +1 -0
- package/dist/mcp-EFDUKJ5V.js +1 -0
- package/dist/provider-EOI5PTFH.js +13 -0
- package/dist/release-74J5ZIL3.js +1 -0
- package/dist/restore-FFGYV7NO.js +3 -0
- package/dist/secret-7FKKTLHB.js +1 -0
- package/dist/setup-PAKRCAFO.js +1 -0
- package/dist/signin-AP3D4XM4.js +12 -0
- package/dist/status-RMWNHOEK.js +4 -0
- package/dist/teardown-E4JNKAZJ.js +22 -0
- package/dist/update-DWVZFNPS.js +1 -0
- package/dist/workspace-CJC5I66L.js +21 -0
- package/package.json +19 -16
- package/skills/build-every-app/SKILL.md +199 -0
- package/skills/build-every-app/patterns.md +140 -0
- package/skills/everyapp/SKILL.md +292 -0
- package/skills/everyapp/mcp.md +350 -0
- package/skills/everyapp/security-review.md +61 -0
- package/skills/everyapp/setup/README.md +274 -0
- package/skills/everyapp/setup/access.md +178 -0
- package/skills/everyapp/setup/context.md +117 -0
- package/skills/everyapp/setup/dataforseo.md +287 -0
- package/skills/everyapp/setup/email.md +366 -0
- package/skills/everyapp/setup/gateway.md +243 -0
- package/skills/everyapp/setup/google.md +360 -0
- package/skills/everyapp/setup/microsoft-365.md +281 -0
- package/skills/everyapp/setup/openai.md +318 -0
- package/skills/everyapp/setup/openrouter.md +309 -0
- package/skills/everyapp/setup/providers.md +1253 -0
- package/skills/everyapp/setup/remote-mcp.md +199 -0
- package/skills/everyapp/setup/signin-apple.md +178 -0
- package/skills/everyapp/setup/signin-cloudflare.md +148 -0
- package/skills/everyapp/setup/signin-github.md +139 -0
- package/skills/everyapp/setup/signin-google.md +178 -0
- package/skills/everyapp/setup/signin-microsoft.md +183 -0
- package/skills/everyapp/setup/signin-oidc.md +163 -0
- package/skills/everyapp/setup/slack.md +344 -0
- package/skills/everyapp/setup/workers-ai.md +138 -0
- package/bin/__everyapp_bash_complete.js +0 -12
- package/dist/bash-complete.js +0 -3
- package/dist/chunk-7BOQJFI5.js +0 -8
- package/dist/chunk-7YVJFS4A.js +0 -1
- package/dist/chunk-BIXKPCDH.js +0 -2
- package/dist/chunk-DLGPLHBH.js +0 -47
- package/dist/chunk-FD6K2YA7.js +0 -9
- package/dist/chunk-GAJEQYJH.js +0 -39
- package/dist/chunk-O2KDOP5R.js +0 -13
- package/dist/chunk-OI2MBGBG.js +0 -4
- package/dist/chunk-POSDLD3G.js +0 -8
- package/dist/chunk-RB5D2R45.js +0 -1
- package/dist/chunk-U4LIQ5VR.js +0 -1
- package/dist/chunk-VEYSNPDH.js +0 -3
- package/dist/chunk-VP6SKW44.js +0 -7
- package/dist/chunk-WO3NE7ZU.js +0 -7
- package/dist/chunk-XTO2VTPY.js +0 -6
- package/dist/chunk-YJ2DKIZS.js +0 -1
- package/dist/create-DYQ3NBWJ.js +0 -22
- package/dist/deploy-PYTCMDGV.js +0 -7
- package/dist/deploy-RMAHOA4Z.js +0 -55
- package/dist/dev-SAE237FS.js +0 -0
- package/dist/generateConfig-46Z3ERF3.js +0 -1
- package/dist/login-B6EF3SMX.js +0 -1
- package/dist/logout-XMKZBLNV.js +0 -1
- package/dist/remoteD1Shell-A67JMO3H.js +0 -6
- package/dist/setupLocal-TZJUW5ES.js +0 -6
- package/gateway/every-app-gateway-build.tar.gz +0 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# OpenRouter for the Gateway
|
|
2
|
+
|
|
3
|
+
OpenRouter is one API key in front of many model providers (OpenAI,
|
|
4
|
+
Anthropic, Meta, Moonshot and others), prepaid in US dollars. The Gateway
|
|
5
|
+
holds the key as `OPENROUTER_API_KEY` and proxies `/api/ai/openrouter/...`
|
|
6
|
+
to `openrouter.ai` for every app that lists the `openrouter` provider, so no
|
|
7
|
+
app holds it. OpenSEO uses it for SAM (the in-app SEO agent), prompt
|
|
8
|
+
suggestions and website research. Open CRM uses it for its research agent
|
|
9
|
+
and web research (Perplexity's Sonar models). agentic-inbox uses it when
|
|
10
|
+
its Worker was deployed with `AI_PROVIDER=openrouter` (its
|
|
11
|
+
`cloudflare.config.ts` still defaults the variable to `workers-ai` until
|
|
12
|
+
the inbox's PR #6 merges; the other provider is
|
|
13
|
+
[workers-ai.md](workers-ai.md)). At
|
|
14
|
+
the end the person has an OpenRouter account with credits, one key with a
|
|
15
|
+
spending limit and no expiry, the key on the Gateway, and a model answering
|
|
16
|
+
inside the app.
|
|
17
|
+
|
|
18
|
+
## Settings
|
|
19
|
+
|
|
20
|
+
| NAME | Required or optional | What it holds |
|
|
21
|
+
| -------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
|
|
22
|
+
| `OPENROUTER_API_KEY` | required by every app whose manifest lists `openrouter` | the API key exactly as OpenRouter showed it once at creation (`sk-or-v1-...`, one line) |
|
|
23
|
+
|
|
24
|
+
The Gateway sends the key only to `https://openrouter.ai`, and only on POST
|
|
25
|
+
to `/api/v1/chat/completions`, `/api/v1/completions`, `/api/v1/responses`
|
|
26
|
+
and `/api/v1/embeddings`.
|
|
27
|
+
|
|
28
|
+
## Costs and plans
|
|
29
|
+
|
|
30
|
+
As of October 2026: an account is free; credits are prepaid in USD and pay
|
|
31
|
+
for inference at the providers' own prices, with no markup. Buying credits
|
|
32
|
+
costs a fee: 5.5% of the amount with a minimum fee of $0.80 by card or
|
|
33
|
+
AliPay, 5% flat in USDC; at least $5 per purchase, at most $25,000; the fee
|
|
34
|
+
is not refunded. OpenRouter may expire unused credits 365 days after
|
|
35
|
+
purchase. The models OpenSEO and the inbox use are all paid (per million tokens,
|
|
36
|
+
from the public model list on 2026-10-23): `openai/gpt-5.6-luna` $0.20 in /
|
|
37
|
+
$1.20 out, `anthropic/claude-haiku-5.5` $0.10 / $0.50,
|
|
38
|
+
`meta-llama/llama-4-scout` $0.10 / $0.30, `meta-llama/llama-3.1-8b-instruct`
|
|
39
|
+
$0.05 / $0.08, `moonshotai/kimi-k2.6` $0.65 / $3.41, `minimax/minimax-m3`
|
|
40
|
+
$0.30 / $1.20. Paid models have no platform request cap; a negative balance
|
|
41
|
+
makes every call fail. `:free` models are capped at 20 requests a minute and
|
|
42
|
+
50 a day (1,000 a day once $10 of credits were ever bought), and the apps
|
|
43
|
+
never ask for one. $10 is a sensible first top-up: the $0.80 minimum fee
|
|
44
|
+
makes $5 cost $5.80 and $10 cost $10.80, and either is enough to set up and
|
|
45
|
+
try the apps.
|
|
46
|
+
|
|
47
|
+
## Only a person can
|
|
48
|
+
|
|
49
|
+
- Sign up or sign in at openrouter.ai and accept its terms.
|
|
50
|
+
- Buy credits (a card, AliPay or USDC) and decide how much.
|
|
51
|
+
- Choose the account's privacy settings (which providers may train on
|
|
52
|
+
prompts; zero data retention per model group).
|
|
53
|
+
- Create the key, pick its spending limit and expiry, and copy it off the
|
|
54
|
+
screen.
|
|
55
|
+
- Delete a key on OpenRouter's side.
|
|
56
|
+
|
|
57
|
+
## Before you start
|
|
58
|
+
|
|
59
|
+
1. `pnpm everyapp secret list openseo --json`,
|
|
60
|
+
`pnpm everyapp secret list crm --json` and
|
|
61
|
+
`pnpm everyapp secret list agentic-inbox --json`, from any directory, one
|
|
62
|
+
per app the person has (`APP_NOT_FOUND`, "<app> isn't deployed to this
|
|
63
|
+
Gateway yet", means that app isn't deployed: the key can still be set
|
|
64
|
+
now, from any directory, and the app uses it on its first deploy). The
|
|
65
|
+
`OPENROUTER_API_KEY` entry in `data.app.setup.unmet` (`names`,
|
|
66
|
+
`need.kind` `required`, `holder` `gateway`, `setup`
|
|
67
|
+
`setup/openrouter.md`) means this file applies, and the app doesn't open
|
|
68
|
+
until it is set: the Gateway lists it as needing setup, sends a browser
|
|
69
|
+
opening `https://<app>.<app base domain>` to its setup dialog and
|
|
70
|
+
answers anything else 503 `app_needs_setup`. `data.app.setup.command`
|
|
71
|
+
is `pnpm everyapp configure <app id>`, which asks for every missing
|
|
72
|
+
setting (`data.next` repeats it). The entry in `data.app.setup.settings`
|
|
73
|
+
with `"set": true` means it is set already: ask before replacing it; a
|
|
74
|
+
value can't be read back, so replacing means a new key (see Rerun,
|
|
75
|
+
rotate, remove). The older fields still say the same:
|
|
76
|
+
`data.gateway.needed[]` has `{ "name": "OPENROUTER_API_KEY", "required":
|
|
77
|
+
true, "set": false }` and `data.gateway.missing` names it while unset.
|
|
78
|
+
This is how an agent lands here: `status` (under "<app> needs setup") and
|
|
79
|
+
`secret list <app id>` (under the unmet setting) print `Guide:
|
|
80
|
+
.claude/skills/everyapp/setup/openrouter.md`, and `secret list --json`
|
|
81
|
+
carries the path as the entry's `setup` (in the
|
|
82
|
+
checkout: `packages/cli/skills/everyapp/setup/openrouter.md`).
|
|
83
|
+
agentic-inbox: its manifest requires `openrouter` and marks
|
|
84
|
+
`workers-ai` `optional: true`, so `OPENROUTER_API_KEY` is in `unmet` and
|
|
85
|
+
`WORKERS_AI_API_TOKEN` only in `settings` with `set: false`
|
|
86
|
+
(`data.app.setup.groups` is `[]`): the inbox opens with this key and its
|
|
87
|
+
email sender ([email.md](email.md)); [workers-ai.md](workers-ai.md) only
|
|
88
|
+
for a Worker built with `AI_PROVIDER=workers-ai`. An app that doesn't
|
|
89
|
+
need OpenRouter: stop here.
|
|
90
|
+
2. `pnpm everyapp status --json`: in the `done` event, `data.installed` and
|
|
91
|
+
`data.claimed` are true, `data.gatewayUrl` is `https://<gateway host>`,
|
|
92
|
+
and `data.apps[]` has an entry with `"id": "openseo"`, `"id": "crm"` or
|
|
93
|
+
`"id": "agentic-inbox"` and `"bound": true`, carrying the same `setup`;
|
|
94
|
+
while a required setting is missing `data.fixes` has `APP_NEEDS_SETUP`
|
|
95
|
+
for the app (severity `warning`, headline "<app> needs setup", `run` the
|
|
96
|
+
same command). Not installed or no owner: [gateway.md](gateway.md) first.
|
|
97
|
+
|
|
98
|
+
## Steps
|
|
99
|
+
|
|
100
|
+
1. **You:** run the two checks above and tell the person what is set and
|
|
101
|
+
what is missing. Say what OpenRouter is for in one line (the model behind
|
|
102
|
+
SAM, the CRM's research agent, or the inbox agent). Ask whether they already have an OpenRouter
|
|
103
|
+
account or key: an account skips 2 (and 3 when it has credits); a key
|
|
104
|
+
whose value they still have (OpenRouter shows it once, at creation) goes
|
|
105
|
+
in with `--from-env` from their shell (step 6's alternative) and skips 5,
|
|
106
|
+
with two checks: the key OpenRouter made for them during onboarding has a
|
|
107
|
+
$100 limit and expires after 180 days, and Verify 2 shows any key's
|
|
108
|
+
`data.expires_at`. Then give steps 2-6 as one list, the default path only
|
|
109
|
+
(the alternatives in 5 and 6 when the answer calls for them), and wait
|
|
110
|
+
after 6.
|
|
111
|
+
2. **Person:** open https://openrouter.ai/sign-in. Sign in, or choose Sign
|
|
112
|
+
Up and create an account: Google, GitHub, or an email address (a code or
|
|
113
|
+
link is sent, then a password); a MetaMask wallet and passkeys are
|
|
114
|
+
offered too. The page needs JavaScript. Done when the top-right menu
|
|
115
|
+
shows their account.
|
|
116
|
+
3. **Person:** open https://openrouter.ai/settings/credits. Click the
|
|
117
|
+
button to add credits (its goal: top up the prepaid balance), enter an
|
|
118
|
+
amount ($10 to start; $5 is the minimum), pay by card, AliPay or USDC.
|
|
119
|
+
Done when the page shows the new balance. Without credits every call
|
|
120
|
+
answers 402.
|
|
121
|
+
4. **Person (optional, read it with them):** open
|
|
122
|
+
https://openrouter.ai/settings/privacy. One set of toggles decides
|
|
123
|
+
whether OpenRouter may route to providers that train on prompts,
|
|
124
|
+
separately for paid and free models; a second set switches zero data
|
|
125
|
+
retention on per model group (Anthropic, OpenAI, Google, all other
|
|
126
|
+
models), which drops that group's first-party endpoints. Leaving
|
|
127
|
+
training off is fine for the apps' models (unverified for every provider
|
|
128
|
+
of each model; the public API doesn't show it). A model with no endpoint
|
|
129
|
+
left under the policy fails with a 404 "0 endpoints out of N requested
|
|
130
|
+
are available matching your guardrail restrictions and data policy ..."
|
|
131
|
+
(older wording: "No endpoints found matching your data policy").
|
|
132
|
+
5. **Person:** open https://openrouter.ai/settings/keys. Click **Create
|
|
133
|
+
Key** (label unverified; OpenRouter's docs name no button; its goal: a
|
|
134
|
+
new key for the Gateway). Name it `every-app gateway <gateway host>`.
|
|
135
|
+
Credit limit: an amount they are happy to lose, e.g. $20. Limit reset:
|
|
136
|
+
monthly; without a reset the limit is for the key's lifetime, and a key
|
|
137
|
+
that reaches it is refused until the limit is raised on the key's page
|
|
138
|
+
or, with a reset, until it resets. Expiration: No expiration, or write
|
|
139
|
+
the date down as the rotation deadline (an expired key fails with 401).
|
|
140
|
+
Create. The key is shown once: copy it now and keep the tab open until
|
|
141
|
+
step 6 is verified. Alternative, README way two, when the person
|
|
142
|
+
exported a management key (made at
|
|
143
|
+
https://openrouter.ai/settings/management-keys) before starting you:
|
|
144
|
+
`curl -s -X POST https://openrouter.ai/api/v1/keys -H "Authorization: Bearer $OPENROUTER_MANAGEMENT_KEY" -H 'Content-Type: application/json' -d '{"name":"every-app gateway <gateway host>","limit":20,"limit_reset":"monthly"}' | jq -r '.key' | pnpm everyapp secret set OPENROUTER_API_KEY --json`
|
|
145
|
+
creates the key and sets it without showing it (the response's
|
|
146
|
+
top-level `key`; `data.hash` names it later). A management key can
|
|
147
|
+
create and delete every key and read spend, so prefer the console unless
|
|
148
|
+
they already have one.
|
|
149
|
+
6. **Person:** README way one, the person types it. In a second terminal, in
|
|
150
|
+
the `every-app` folder: `pnpm everyapp configure <app id>` (`openseo`,
|
|
151
|
+
`crm` or `agentic-inbox`: the app that needs it; the key is set once,
|
|
152
|
+
for every app), which asks for this key among the app's other unset
|
|
153
|
+
settings, or `pnpm everyapp secret set OPENROUTER_API_KEY` for just this
|
|
154
|
+
one. The prompt is hidden (`OPENROUTER_API_KEY`, under lines saying what
|
|
155
|
+
it is for and where it comes from; `secret set` asks `Value for
|
|
156
|
+
OPENROUTER_API_KEY`); paste, Enter. It prints
|
|
157
|
+
`Set OPENROUTER_API_KEY on the Gateway`. Then they tell you.
|
|
158
|
+
Alternative, README way three, when the key is in a variable the person
|
|
159
|
+
exported before starting you:
|
|
160
|
+
`pnpm everyapp configure <app id> --from-env --json` (the `done` event's
|
|
161
|
+
`data.set` holds `OPENROUTER_API_KEY`; `data.changed.gateway.versions`
|
|
162
|
+
maps the Gateway Worker to its new version id) or
|
|
163
|
+
`pnpm everyapp secret set OPENROUTER_API_KEY --from-env OPENROUTER_API_KEY --json`
|
|
164
|
+
(its `data.gateway.names` contains `OPENROUTER_API_KEY`;
|
|
165
|
+
`data.gateway.versions` the same map). Never `echo` the variable and
|
|
166
|
+
never put the key on a command line. The change is live at once; no
|
|
167
|
+
deploy.
|
|
168
|
+
7. **You:** verify (next section). The tab from step 5 can be closed once
|
|
169
|
+
the key answers there (Verify 2 on the `--from-env` path, otherwise 3).
|
|
170
|
+
8. **You, agentic-inbox only:** the provider is chosen when its Worker is
|
|
171
|
+
built, from the `AI_PROVIDER` variable of the deploying shell; the
|
|
172
|
+
default is still `workers-ai` (the inbox's PR #6 flips it to OpenRouter;
|
|
173
|
+
open). Pass it on every deploy, in the app's directory:
|
|
174
|
+
`AI_PROVIDER=openrouter pnpm everyapp deploy --json`. OpenSEO and Open
|
|
175
|
+
CRM need no redeploy.
|
|
176
|
+
|
|
177
|
+
## Verify
|
|
178
|
+
|
|
179
|
+
1. `pnpm everyapp secret list <app id> --json` for each app (`openseo`,
|
|
180
|
+
`crm`, `agentic-inbox`), from anywhere: the `OPENROUTER_API_KEY` entry in
|
|
181
|
+
`data.app.setup.settings` has `"set": true` and has left
|
|
182
|
+
`data.app.setup.unmet`; `data.app.setup.ready` is true once nothing else
|
|
183
|
+
of the app's is missing (OpenSEO: its DataForSEO key; Open CRM: its
|
|
184
|
+
Context key; agentic-inbox: its email sender. `WORKERS_AI_API_TOKEN` and
|
|
185
|
+
OpenSEO's Context key are optional: in `settings` with `set: false`,
|
|
186
|
+
never in `unmet`). In the older fields, `data.gateway.names`
|
|
187
|
+
lists the key, its `data.gateway.needed` entry has `"set": true` and it
|
|
188
|
+
left `data.gateway.missing` (for an app not deployed yet, the root
|
|
189
|
+
`pnpm everyapp secret list --json` shows `data.gateway.names` and that is
|
|
190
|
+
the check). Then `pnpm everyapp status --json`: each app's `setup.ready`
|
|
191
|
+
is true and `data.fixes` has no `APP_NEEDS_SETUP` for it once everything
|
|
192
|
+
else is set; until then the fix stays, naming only what is still missing.
|
|
193
|
+
2. Smoke check, only when the key went in with `--from-env` (step 6's
|
|
194
|
+
alternative: the variable already exists in the person's shell). After
|
|
195
|
+
the hidden prompt nothing is exported, and after the management-key path
|
|
196
|
+
nobody but the Gateway holds the key: don't ask them to export it for a
|
|
197
|
+
check; go to 3, the app, where a $0 balance also shows (as a 402). In
|
|
198
|
+
their terminal, never yours:
|
|
199
|
+
`curl -s -w '\n%{http_code}\n' https://openrouter.ai/api/v1/key -H "Authorization: Bearer $OPENROUTER_API_KEY"`.
|
|
200
|
+
A `{"data":{...}}` body and 200 means the key works: read `data.label`,
|
|
201
|
+
`data.limit` (the step 5 limit, or null), `data.limit_reset` (null means
|
|
202
|
+
a lifetime limit), `data.limit_remaining`, `data.usage`,
|
|
203
|
+
`data.expires_at` (null means never) and `data.is_free_tier` (false once
|
|
204
|
+
credits were ever bought). The balance is not in this response and
|
|
205
|
+
`GET /api/v1/credits` needs a management key: a $0 balance first shows
|
|
206
|
+
as a 402 in 3. An `{"error":...}` body and 401: "User not found." is a
|
|
207
|
+
wrong, disabled or mistyped key; "Missing Authentication header" means
|
|
208
|
+
the variable is empty, so the export failed, not the key. Afterwards:
|
|
209
|
+
`unset OPENROUTER_API_KEY`.
|
|
210
|
+
3. The app. OpenSEO: open `https://openseo.<app base domain>`, a project,
|
|
211
|
+
then its SAM page (the project's `/sam` route) and ask something; the
|
|
212
|
+
answer streams. Prompt suggestions and website research use the same key.
|
|
213
|
+
A browser sent to `https://<gateway host>/?setup=openseo` instead means a
|
|
214
|
+
required setting is still unset (Verify 1 says which): behind the
|
|
215
|
+
Gateway's setup gate none of the three apps opens while this key is
|
|
216
|
+
missing, so the refusals below are what a fork whose manifest marks the
|
|
217
|
+
provider `optional: true` sees. OpenSEO's SAM page itself only checks
|
|
218
|
+
for the Gateway binding, so there the turn fails: the Gateway answers 503
|
|
219
|
+
`ai_provider_not_configured`, visible in the browser's network tab or the
|
|
220
|
+
Gateway's logs (4). OpenSEO's own "OPENROUTER_API_KEY is not set" page
|
|
221
|
+
shows only in local dev. Open CRM: open `https://crm.<app base domain>`;
|
|
222
|
+
its research agent runs on the key. agentic-inbox (deployed with
|
|
223
|
+
`AI_PROVIDER=openrouter`): open
|
|
224
|
+
`https://agentic-inbox.<app base domain>`, a mailbox, and send the agent
|
|
225
|
+
a message; it answers. Its refusal reads "AI isn't set up on this
|
|
226
|
+
gateway yet, so I can't help with this inbox. An admin sets
|
|
227
|
+
OPENROUTER_API_KEY with `pnpm everyapp secret set OPENROUTER_API_KEY`."
|
|
228
|
+
(any other refusal: "The gateway refused the AI call: <message>
|
|
229
|
+
(<code>)").
|
|
230
|
+
4. The Gateway's logs, when the app says nothing useful: every proxied call
|
|
231
|
+
logs one JSON line `{"evt":"ai.proxy.usage","provider":"openrouter","model":...,"status":...,"usage":...}`
|
|
232
|
+
and a failed connection `{"evt":"ai.proxy.upstream_failed",...}`.
|
|
233
|
+
Workers Logs is on for the Gateway Worker: in the Cloudflare dashboard,
|
|
234
|
+
README's path: **Workers & Pages** → `every-app-gateway` → **Observability** (**Logs** on older accounts) → **Live**,
|
|
235
|
+
or the stored logs on the same page (kept 7 days on Workers Paid). `cf workers tail` does not exist in cf 1.0.0-beta.14
|
|
236
|
+
(`cf workers --help`); `cf o11y telemetry live-tail --help` and `cf o11y
|
|
237
|
+
telemetry query --help` are the CLI way, not covered here. `status` is
|
|
238
|
+
OpenRouter's HTTP status: 200 is a billed answer, 402 and 403 are the
|
|
239
|
+
account's problem, not the Gateway's.
|
|
240
|
+
|
|
241
|
+
## If it fails
|
|
242
|
+
|
|
243
|
+
| Error or symptom | Meaning | What to do |
|
|
244
|
+
| -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
245
|
+
| `SECRET_VALUE_REQUIRED` | `secret set --json` ran with nothing piped and no terminal | one of README's three ways; its `data.rerun` is the `--from-env OPENROUTER_API_KEY` form |
|
|
246
|
+
| `SECRET_VALUE_REQUIRED` from `pnpm everyapp configure <app id> --json` | nothing was piped (with `--from-env`, stdin isn't read), no variable of a missing name was found, and there is no terminal; the message names what the app still needs | the person's terminal (step 6), `NAME=value` lines on stdin, or the hidden read then its `data.rerun`, `pnpm everyapp configure <app id> --from-env` |
|
|
247
|
+
| `SECRET_EMPTY` | the `--from-env` variable is empty in your shell (exported in theirs, not before you started) | the person runs the `--from-env` command in their terminal, or the hidden prompt (step 6) |
|
|
248
|
+
| `SECRET_SEVERAL_NAMES` | `--from-env` or a pipe with more than one name | one name per call |
|
|
249
|
+
| `SECRET_NOT_DECLARED` with `data.didYouMean` | the name is misspelt (`OPEN_ROUTER_API_KEY`) | rerun with the name in `data.didYouMean` and the same value source (`--from-env VAR --json`, or the same pipe); `data.rerun` carries only the names, so run as is it stops with `SECRET_VALUE_REQUIRED` |
|
|
250
|
+
| `provider_not_allowed` (403) | the app's `everyapp.config.ts` `providers` doesn't list `openrouter` | add it and redeploy; nothing to set on the Gateway |
|
|
251
|
+
| a browser opening the app is sent to `https://<gateway host>/?setup=<app id>`; any other request gets 503 with the body `{"error":"app_needs_setup","app":"<app id>"}` | the Gateway's setup gate: a required setting of the app is still unset (this key, or another the manifest requires: agentic-inbox's email sender, OpenSEO's DataForSEO key, Open CRM's Context key) | `data.app.setup.command`, `pnpm everyapp configure <app id>` (step 6), then Verify 1 |
|
|
252
|
+
| `ai_provider_not_configured` (503, `x-everyapp-error`) | the Gateway holds no `OPENROUTER_API_KEY` (behind the setup gate an app whose manifest requires `openrouter` doesn't open in this state; one that marks it `optional: true` sees this) | step 6, then Verify 1; check the name |
|
|
253
|
+
| `model_not_allowed` (403) | the app's manifest `ai.models` doesn't list the model it asked for (agentic-inbox's `AGENT_MODEL`) | use a listed model, or add it to `ai.models` and redeploy; OpenSEO lists none, so any model passes |
|
|
254
|
+
| `ai_route_not_allowed` (403) | the app called a path that isn't inference | only the four routes under Settings; nothing to set |
|
|
255
|
+
| `ai_upstream_failed` (502) | the Gateway couldn't reach openrouter.ai | retry; read the `ai.proxy.upstream_failed` log line |
|
|
256
|
+
| `integration_not_configured` | a different capability's setting is missing: DataForSEO, Context or email sending, not OpenRouter | [dataforseo.md](dataforseo.md), [context.md](context.md), [email.md](email.md) |
|
|
257
|
+
| OpenRouter 401 "User not found." | the key is wrong, disabled, deleted, or pasted with a stray character | create a new key (Rerun, rotate, remove) |
|
|
258
|
+
| OpenRouter 401 "API key expired" | the key's Expiration (step 5) passed (wording from the management-key docs; unverified for an inference key) | a new key with No expiration (Rotate) |
|
|
259
|
+
| OpenRouter 401 "Missing Authentication header" / "No cookie auth credentials found" | the header was sent empty (the variable isn't exported in that terminal) or not at all; the key wasn't judged | redo the export in one terminal, then Verify 2; or step 6 |
|
|
260
|
+
| OpenRouter 402 "insufficient credits" | the balance is zero or negative | add credits at https://openrouter.ai/settings/credits |
|
|
261
|
+
| OpenRouter 403 with `limit_source: openrouter_key_limit` | the key's own credit limit (step 5) is spent; `resets_at: null` means a lifetime limit | raise it on the key's page (the only fix for a lifetime limit), or wait for `resets_at` |
|
|
262
|
+
| OpenRouter 403 guardrail or moderation (`permission_denied`) | the prompt was flagged, or a workspace guardrail blocked the request; not a setup problem | nothing to set |
|
|
263
|
+
| OpenRouter 404 "0 endpoints out of N requested are available matching your guardrail restrictions and data policy" (older: "No endpoints found matching your data policy") | the privacy settings (training, or a zero-data-retention toggle for the model's group) exclude every endpoint of that model | https://openrouter.ai/settings/privacy, or another model |
|
|
264
|
+
| OpenRouter 429 | rate limited: a `:free` model's cap, or the upstream provider | the apps' models are paid, so retry; OpenRouter routes to another provider when it can |
|
|
265
|
+
| OpenRouter 502 / 503 | the model is down, or no provider meets the routing requirements (`zdr`, provider order) | retry later; OpenSEO's MiniMax fallback restricts routing to zero-data-retention endpoints (Together first, fallbacks on), so a 503 there means no ZDR provider is up |
|
|
266
|
+
| OpenRouter 403 "This model is not available in your region" | OpenRouter refuses OpenAI, Anthropic and Google models from some countries (community reports, 2026; not in OpenRouter's docs) | OpenSEO switches SAM to `minimax/minimax-m3` by itself; agentic-inbox's agent defaults to Claude Haiku, so redeploy it with `AGENT_MODEL=moonshotai/kimi-k2.6 AI_PROVIDER=openrouter pnpm everyapp deploy --json` (or `meta-llama/llama-4-scout`, also in its `ai.models`) |
|
|
267
|
+
| agentic-inbox: "AI isn't set up on this gateway (OPENROUTER_API_KEY) or in .dev.vars" | no Gateway binding and no local key: `everyapp dev`, whose ready block's `Dev vars` line names the keys `.dev.vars` is missing (the inbox's names both providers' settings; on OpenRouter only `OPENROUTER_API_KEY` is needed) | the person adds `OPENROUTER_API_KEY=...` to the app's `.dev.vars` (gitignored) in their own editor, with their own key, billed to them; never ask for the value and never write that file yourself |
|
|
268
|
+
| OpenSEO SAM page: "OPENROUTER_API_KEY is not set for this deployment yet" | the same, in local dev (its `Dev vars` line names the key too); behind the Gateway the page never says this | `.dev.vars` as above, by the person |
|
|
269
|
+
|
|
270
|
+
## Rerun, rotate, remove
|
|
271
|
+
|
|
272
|
+
- **Rerun.** Every step is safe to repeat: `configure` and `secret set`
|
|
273
|
+
replace the value, the keys page shows what exists. Start from Verify and
|
|
274
|
+
continue at the first step that isn't done.
|
|
275
|
+
- **Rotate.** Create a new key (step 5, No expiration), set it (step 6), run
|
|
276
|
+
Verify, then the person deletes the old key at
|
|
277
|
+
https://openrouter.ai/settings/keys. Apps pick up the new value on their
|
|
278
|
+
next call; no deploy. A key with an Expiration date needs this before the
|
|
279
|
+
date.
|
|
280
|
+
- **Remove.** `pnpm everyapp secret unset OPENROUTER_API_KEY --json` (it asks
|
|
281
|
+
at a terminal; with `--json` add `--yes` only when the person said so).
|
|
282
|
+
Then the person deletes the key on OpenRouter: a key the Gateway no longer
|
|
283
|
+
holds is still a key. Apps whose manifest requires `openrouter` then need
|
|
284
|
+
setup again: the Gateway closes them until the key is back (OpenSEO, Open
|
|
285
|
+
CRM and agentic-inbox alike, and the inbox's `AI_PROVIDER=workers-ai` build
|
|
286
|
+
changes nothing: the manifest, not the build, says what is required;
|
|
287
|
+
`status` says so, with this file's path). An app that marks the provider
|
|
288
|
+
`optional: true` keeps opening and gets `ai_provider_not_configured` on
|
|
289
|
+
each call instead.
|
|
290
|
+
|
|
291
|
+
## Sources
|
|
292
|
+
|
|
293
|
+
- https://openrouter.ai/docs/api_reference/authentication (keys at `/settings/keys`, credit limit and reset on a key, onboarding keys' $100 limit and 180 days, Bearer header)
|
|
294
|
+
- https://openrouter.ai/docs/api/api-reference/api-keys/get-current-api-key.md (`GET /api/v1/key` and its fields; no balance)
|
|
295
|
+
- https://openrouter.ai/docs/api/api-reference/api-keys/create-a-new-api-key.md (`POST /api/v1/keys`: `limit`, `limit_reset`, `expires_at`; top-level `key` shown once; management key required)
|
|
296
|
+
- https://openrouter.ai/docs/api/api-reference/credits/get-remaining-credits.md (`GET /api/v1/credits` needs a management key; 403 otherwise)
|
|
297
|
+
- https://openrouter.ai/docs/guides/overview/auth/management-api-keys (`/settings/management-keys`, Create New Key, no completion calls, 401 "API key expired")
|
|
298
|
+
- https://openrouter.ai/docs/api_reference/limits (free-model caps, paid models uncapped, negative balance, `is_free_tier`)
|
|
299
|
+
- https://openrouter.ai/docs/api_reference/errors-and-debugging (401, 402, 403 guardrail and `permission_denied`, 429, 502, 503; key-limit 403 with `limit_source`, `scope`, `resets_at`)
|
|
300
|
+
- https://openrouter.ai/blog/announcements/simplifying-our-platform-fee/ and https://openrouter.ai/terms §4.1-4.2 (5.5% with a $0.80 minimum, 5% in crypto; $5 to $25,000 a purchase; 365-day expiry); https://openrouter.ai/docs/faq (payment methods, no inference markup)
|
|
301
|
+
- https://openrouter.ai/docs/guides/privacy/provider-logging (`/settings/privacy`, paid and free settings), https://openrouter.ai/docs/guides/features/zdr (ZDR toggle per model group), https://openrouter.ai/docs/guides/routing/provider-selection (404 when no provider matches; `order`, `zdr`, `allow_fallbacks`)
|
|
302
|
+
- https://github.com/NousResearch/hermes-agent/issues/133850 (2026-10-06; the data-policy 404 body, old and new wording)
|
|
303
|
+
- https://clerk.openrouter.ai/v1/environment (sign-in options; fetched 2026-10-23)
|
|
304
|
+
- https://linux.do/t/topic/1846933 and https://github.com/anomalyco/opencode/issues/19117 (2026; 403 "not available in your region" for OpenAI, Anthropic and Google models through OpenRouter)
|
|
305
|
+
- https://developers.cloudflare.com/workers/observability/logs/workers-logs/ (Workers & Pages, the Worker, Observability; 7 days on Paid); `cf o11y telemetry --help` (live-tail, query)
|
|
306
|
+
- https://openrouter.ai/docs/guides/routing/model-variants/free.md (`:free` variants)
|
|
307
|
+
- https://openrouter.ai/api/v1/models (public; the six model ids and prices above, fetched 2026-10-23)
|
|
308
|
+
- Console pages checked on 2026-10-23: https://openrouter.ai/settings/keys (via `/workspace-redirect/keys`), https://openrouter.ai/settings/credits and https://openrouter.ai/settings/privacy all go to sign-in when signed out; the older `/docs/api-reference/...` and `/docs/features/...` URLs 308-redirect to the pages above
|
|
309
|
+
- In code: `apps/every-app-gateway/src/server/app-gateway-entrypoint.ts` (`provider_not_allowed`), `apps/every-app-gateway/src/server/capabilities/email.ts` (`integration_not_configured`), `apps/every-app-gateway/src/server/app-needs-setup.ts` (the setup gate: the redirect to `/?setup=<app id>` and 503 `app_needs_setup`), `packages/sdk/src/internal/gatewaySettings.ts` (each provider's key is `required`), `packages/sdk/src/internal/appSettings.ts` (`AppSetup`: `unmet`, `settings`, `groups`, `command`; `needOf`: a plain provider id is required, `anyOf` makes a group; `setup/openrouter.md` from the provider registry, `packages/sdk/src/internal/aiProviders.ts`), `packages/cli/src/commands/secret/index.ts` (`secret list <app>` from anywhere, `data.app.setup`, the kept `data.gateway.needed` and `missing`, `APP_NOT_FOUND`), `packages/cli/src/commands/configure/index.ts` (`configure <app>`: the prompts, `NAME=value` lines on stdin, `--from-env`, `SECRET_VALUE_REQUIRED`), `packages/cli/src/lib/app/settings.ts` (the `Guide:` line), `packages/cli/src/commands/status/problems.ts` (`APP_NEEDS_SETUP`), `packages/cli/src/commands/dev/ready.ts` (the `Dev vars` line); agentic-inbox's `everyapp.config.ts` (`openrouter` required, `workers-ai` `optional: true`), `cloudflare.config.ts` (`AI_PROVIDER` defaults to `workers-ai` until its PR #6) and `workers/everyapp/gateway.ts` (`AGENT_MODEL`); OpenSEO's `everyapp.config.ts` (`openrouter` required), `src/server/lib/openrouter.ts` (ZDR routing, blocked countries) and `src/serverFunctions/samAccess.ts` (the SAM gate); Open CRM's `everyapp.config.ts` (`openrouter` required)
|