A1 API Gateway — Product Guide
- Signing in, organisations and roles
- Providers: your vendor keys
- Creating a key
- Changing a key afterwards
- IP access
- Mail keys
- Refusals
- Alerts
- Usage, requests and the audit log
- Money
1. Signing in, organisations and roles
1.1 Sign in
Sign in at a1apigateway.com/login. Enter your email and password and press Continue. Two-factor is required for every account, so the next screen is Two-factor code: type the six digits from your authenticator app. The six boxes accept a paste of the whole code, and the form submits itself as soon as the sixth digit is there; Verify is there for when it does not.
If you cannot reach your authenticator, press Use a recovery code and enter one of the codes you were given when you enrolled. Each recovery code works once. After using one, enrol a new authenticator.
1.2 The first sign-in: two-factor and recovery codes
A new account — yours when the organisation was registered, or anyone you invite — is sent to Set up two-factor authentication before it can go any further. Scan the QR code with any authenticator app, or press can't scan? show the secret and type the secret in by hand, then enter the code the app shows and press Verify and finish setup.
The next screen, Your recovery codes, is shown once and never again. Copy all puts them on the clipboard; put them in your password manager, tick I have stored these codes securely and press Continue. Without them, a lost phone means asking the operator to reset the account.
Screenshot to add: the two-factor enrolment screen — QR code, the six-box code input, and the warning that recovery codes are shown once on the next screen.
1.3 Choosing an organisation
An account can belong to more than one organisation. With exactly one, the console opens it straight away. With several, Choose an organisation lists them, each with its name, your role in it and its address, and a click opens it. Inside the console, the organisation menu in the top right has Switch organisation…, which brings the same list back.
Each organisation has its own address, {slug}.a1apigateway.com, its own database and its own everything else. Opening an organisation you are not a member of gives No access to this organisation rather than an error page.
A newly registered organisation is not usable until its owner has clicked the link in the verification email (valid 24 hours; Resend verification email is on the same screen) and, after that, until the operator has approved it. The console says which of the two it is waiting for.
1.4 What the three roles may do
The console has three roles: owner, admin and viewer. A key's owner field is a team or product name and has nothing to do with these roles, so every change below is made by a person who is an owner or an admin. Viewers see everything and change nothing.
| Action | Owner | Admin | Viewer |
|---|---|---|---|
| See every page: keys, providers, usage, requests, refusals, audit log | yes | yes | yes |
| Export the refusal log as CSV | yes | yes | yes |
| Add, test, rotate, disable or delete a vendor key; change its models, monthly cap or environment; narrow an operator key | yes | yes | no |
| Create a key; change its routes, models, environment, limits or budgets | yes | yes | no |
| Tick Add the next new address automatically, Allow a refused address, remove an address | yes | yes | no |
| Suspend, resume, revoke or rotate a key | yes | yes | no |
| Change organisation settings, alert channels, aliases, voices, API tokens; invite or remove admins and viewers | yes | yes | no |
| Invite, promote or remove an owner | yes | no | no |
| Export the organisation's data, grant the operator write access, close the organisation | yes | no | no |
The server enforces this, not the console: a viewer who calls the API directly is refused with "Viewers cannot make changes.", and an admin attempting an owner action with "This action is reserved for the organisation owner." An organisation always keeps at least one owner; removing or demoting the last one is refused.
Every change writes a row to the audit log with who made it (§9.4).
1.5 Members
Members live on the Organisation page. + Invite member asks for an email address and a role — owners may also invite another owner. The invitee gets a link valid for seven days, sets a password and enrols two-factor before joining. Inviting an address that already has a pending invitation replaces the earlier one, and the earlier link stops working. Pending invitations can be sent again (Resend, which also invalidates the previous link) or withdrawn (Revoke).
Changing someone's role is a drop-down in the members table. Remove takes them out of this organisation immediately; their account and their other memberships are untouched.
1.6 Operator support sessions
The platform operator can open a support session on your organisation. It is read-only unless an owner grants a window from Organisation → Your data → Grant support write access, which asks for a number of minutes. Your own vendor key secrets are never visible to the operator, and every support session is recorded in your audit log.
1.7 Getting around
The left-hand navigation is short on purpose: Dashboard, Keys and Providers at the top; Refusals, Alerts and Audit log under Operate; Organisation under Settings. Until the organisation has its first key, the dashboard is replaced by a Get started checklist: verify email and set up two-factor, add your own vendor key or request prepaid credit, create your first key, add an IP rule, send a test request, invite a teammate.
2. Providers: your vendor keys
The Providers page is where the organisation's own vendor accounts live. One section per provider — Anthropic, OpenAI, xAI, ElevenLabs, AssemblyAI and SendGrid — each showing your keys for it, any key the operator has assigned to you, and the models your plan allows.
The distinction that matters on this page: requests through your own key are billed by the vendor directly to you and never deducted from credit. Requests through an operator-assigned key come out of your prepaid credit. You can add the same provider as often as you like under different labels — one per environment, say — and then point each virtual key at the one it should use.
Screenshot to add: the Providers page with two vendor key cards for one provider, one of them the default, showing the models line, the spend-cap bar and the row of buttons.
2.1 Adding a key
+ Add provider key at the top of the page, or + Add {Provider} key inside a section, opens Add provider key:
| Field | What it is |
|---|---|
| Provider | Which vendor the secret belongs to. |
| Kind | Inference · routes requests is the normal choice. Admin · usage reconciliation only stores a vendor admin key that is used solely by the nightly reconciliation and never routes a request. SendGrid has only Mail · sends messages. |
| Label | Your name for this key, unique within the organisation. The suggestion buttons offer {provider}-production, {provider}-development and {provider}-testing. The label is what every error message, ledger row and routing menu shows, so make it say which account it is. |
| API key | The vendor secret. Encrypted inside your organisation's own database file; only the last characters are ever shown again, to anyone. |
| Vendor workspace / project / account (optional) | Helps you match this key to a line in the vendor's own invoice. |
| Environment (optional) | Not set, Development, Staging or Production. See §2.6. |
| Monthly spend cap (optional) | Dollars. See §2.7. |
| Make it the {Provider} default for new virtual keys | Ticked automatically when the provider has no default yet; otherwise it says it replaces the current default. |
Test & save sends one tiny request to the vendor before storing anything, and reports back "Test passed · 412 ms with claude-sonnet-5" or the vendor's own refusal. A key that fails the test is still stored, marked error, so you can rotate the secret or delete it rather than retyping everything. An admin-kind key is not tested, so its button says Save.
A new key allows every model its provider offers inside your plan. Narrow it afterwards from its Models button, where the console can tell you which virtual keys a narrowing would affect (§2.5).
2.2 The key card
Each key of your own is a card carrying its label, its status, a default badge if it is the provider's default, and its environment badge if it has one. The rows are the things an admin comes here to check:
| Row | Meaning |
|---|---|
| Secret | The last characters only — write-only; rotate to replace. |
| Models | "all 14, including new ones" or "8 of 14 switched on". |
| Spend cap | A bar of this month's spend against the cap, or no cap. |
| Added, Last used | When it was stored, and when the gateway last routed a request through it. |
| Month to date | The ledger's own total for this key, with the request count. |
| Virtual keys | Every key bound to it, each a link. "none bound · used by keys on the organisation default" when it is the default. |
The buttons under the card are Test, Models, Make default, Rotate secret, Disable (or Enable) and Delete.
2.3 Testing, rotating, disabling, deleting
Test sends the same tiny request the add dialog sends and reports the outcome and latency. Use it when a key starts refusing: it separates "the secret is wrong" from "the vendor is having a bad morning".
Rotate secret takes the new vendor secret and replaces the old one immediately — the old one is not kept and cannot be shown. Virtual keys bound to this vendor key keep working without any change, because they are bound to the key, not to the secret. For an inference key the button is Replace & test, so a bad paste is caught at once.
Disable stops the key routing anything; virtual keys pinned to it fail closed. Delete wipes the secret from your database and is refused while virtual keys still route through it — the dialog names them, each a link, so you can re-route or revoke them first. Usage history is kept either way.
Two status callouts appear on the card when they apply: error ("The last test failed, so requests cannot route through this key") and unhealthy ("The vendor rejected the last request through this key").
2.4 A vendor key's model list
Every vendor key carries its own list of models. It is the answer to a question the gateway used to have no place for: this account is for the support bot, and the support bot has no business calling the most expensive model in the catalogue.
Models on the key card opens a panel from the right with two modes:
- All models, including new ones — everything the plan allows for this provider, now and when the operator adds more. The default.
- Only the models I tick — an explicit list. A model added to the catalogue later stays off until you tick it.
The models are grouped by what they do, with the endpoint each group answers on — Chat (POST /v1/chat/completions), Image generation (POST /v1/images/generations), Embeddings (POST /v1/embeddings), Speech (POST /v1/audio/speech), Transcription (POST /v1/audio/transcriptions) — and each model shows its price in the vendor's own unit. There is a search box, and all / none per group. The footer counts "N of M on". Update saves.
At request time the model must be switched on for the vendor key the request is about to use. If it is not, the caller gets 403 model_not_allowed naming both: "Model 'openai/gpt-6-astra' is not switched on for vendor key 'openai-development'. An admin can switch it on under Providers → Models." A model switched off is a decision, not an outage, so the request does not quietly fall back to another vendor key to find the model elsewhere.
2.5 The warning before you narrow a list
Narrowing a list can break something that is running. Before saving, the panel asks the server which virtual keys would lose which models and shows the answer:
Virtual keys that would lose models: AIAgentWorker Prod - AI uses openai/gpt-5.6, openai/gpt-5.6-mini through this key Support bot uses openai/gpt-5.6 through this key (it follows this key's list) Requests from them for these models will be refused with 403 once you update.
The button then reads Update anyway. Nothing is saved by the first press; it only asks. A key marked "it follows this key's list" is one set to Everything this vendor key allows, so it tracks whatever you leave switched on.
Screenshot to add: the Models panel open over the Providers page, models grouped by capability with prices, and the amber "Virtual keys that would lose models" warning above the Update anyway button.
2.6 Environments
A vendor key may be tagged development, staging or production. The tag shows as a coloured badge on cards and lists, and it does one job: a virtual key may only route through vendor keys of its own environment (operator keys, which have no environment, are always allowed).
This is the safety net for keeping environments apart. Without it, a development key left on the organisation default would quietly spend on the production vendor account. With it, the key editor offers only vendor keys that fit, marks the others with the reason, and the API refuses a cross-environment pin with a 400.
The organisation default counts too: a virtual key with an environment may sit on Organisation default only while the default key is of the same environment or has none. Changing a vendor key's environment is refused while virtual keys of another environment depend on it, and the refusal names them. Keys with no environment behave exactly as they did before, so nothing changes until you start tagging.
2.7 A monthly spend cap per vendor key
Each of your own vendor keys can carry an optional monthly cap in dollars, set in the add dialog or on the Spend cap tab of its Models panel. A request that would cross it is refused before it is sent, with 402 vendor_key_cap_reached, and alerts fire at 50, 80 and 95 % of the cap.
A capped-out key counts as unavailable for routing, so a virtual key set to fall back to the organisation default will keep working through another key. It never falls back from your own key to prepaid credit.
The cap is shared: every virtual key routed through this vendor key spends against the same figure. The key wizard's Budgets step shows the caps a new key would share, as bars, so it is visible before the key exists (§3.6).
2.8 Keys the operator assigned to you
Under each provider, keys the operator has assigned to your organisation appear as chips: "Assigned by the operator · deducted from prepaid credit · your own key is preferred", each with its label, whether it is the default, how many models are on, and a Models button.
That button opens the same panel. The choice is yours, inside what the operator allows: you narrow which of that key's models your organisation uses. You cannot widen past the operator's list, and an operator key has no spend cap or environment of its own — so the panel shows the Models tab only. Every route your organisation can use then works the same way, with one list per route and nothing to reconcile.
2.9 The rest of the page
Under each provider's keys, Models in your plan lists everything the plan allows for that provider with its price. It is read-only: which of them a key may use is decided on the vendor key itself, above. Under ElevenLabs there is also Voices, where you give a name — narrator — to an ElevenLabs voice id, so an application can send voice: "narrator" and you can change the voice behind it without a deploy.
Admin keys for reconciliation is a separate table at the bottom, for keys of the admin kind. They let the nightly reconciliation compare the gateway's figures with the vendor's own usage report. They never route inference and are not tested on create.
3. Creating a key
Keys → + Create key opens a six-step wizard: Name & owner, Models & routing, IP access, Rate limits, Budgets, Review. A mail key has a shorter sequence (§6).
The steps are listed down the left, each with a one-line summary of what you have chosen so far, and any of them can be opened directly. Under them, a live This key panel shows the environment, the vendor key per provider and the worst day this key could cost. The footer — Cancel, Back, Next: {step} — stays on screen while you scroll.
3.1 Step 1 — Name & owner
| Field | What it is for |
|---|---|
| Name | Shown in reports, alerts and the refusal log. Make it say which application this is. |
| Owner (team or product) | Usage inside the organisation is grouped by owner. A team or product name, not a person. |
| Environment | Not set, development, staging or production. A production key may only route through production vendor keys, and the same for the others. Leave it unset and the key may use any of them. |
| Service | Two cards. AI — models calls the model endpoints and is limited by requests and dollars. Mail — SendGrid calls /v3/mail/send and is limited by recipients. A key does one job: a leaked mail key cannot spend on models, and a leaked AI key cannot send mail. |
| Expires | A date. Recommended for contractors and trials. |
| Metadata | Optional JSON kept with the key for your own bookkeeping, e.g. {"ticket":"OPS-412"}. |
| Request logging | Record metadata only — model, tokens, cost, latency, client address and outcome for every request. The default. Record the request and response bodies too keeps the prompt and completion text as well, in your organisation's own database, readable by every member with console access. |
3.2 Step 2 — Models & routing
One block per provider, and inside each block the route comes first, because the route decides what the model list can contain.
Route through offers Organisation default — shown with the key it currently means, for example "Organisation default — openai-production" — then every vendor key for that provider, each annotated with whether it is your own key or a platform key and whether it is billed by vendor or prepaid credit. Choosing a key of the wrong environment gives a field error naming both environments rather than a surprise at request time.
Models is then a three-way choice for that provider:
| Choice | What it means |
|---|---|
| Everything this vendor key allows | Sent as {provider}/*: the key follows the vendor key as models are switched on and off for it. The usual choice. |
| Only the ones I tick | Chips, grouped by what they do, offering only the models the chosen vendor key actually allows. All / None per group. |
| Not used by this key | No route is stored for that provider; a request for one of its models is refused with 403 model_not_allowed. |
If the chosen vendor key has nothing switched on, the block says so: "This vendor key has no models switched on. Widen its list under Providers, or pick another key."
Below the provider blocks:
- If the chosen vendor key is unavailable — Fail the request keeps attribution exact: this key's spend only ever appears under the vendor key you picked. Fall back to the organisation default keeps requests working through another key, including when the chosen key has reached its monthly cap.
- Default max tokens (applied when the request omits
max_tokens, and it bounds the worst-case cost estimate) and Maximum max tokens (requests asking for more are rejected). - Alias (optional) — a short name mapped to the first model this key ticks, so production code can say
settlement-defaultand you can move it to a newer model without a deploy. - Allow image generation — a switch, off by default. A picture costs far more than a chat call, so the ceilings are part of the permission: Images per request, Largest image (compared by area, so both orientations of a size fit) and Highest quality (
maxcosts about forty timeslow). The switch is offered only when an image model is available through this key's OpenAI route.
Screenshot to add: wizard step 2 with two provider blocks — one on Everything this vendor key allows, one on Only the ones I tick with model chips grouped by capability — and the steps rail with its summaries on the left.
3.3 Step 3 — IP access
Two choices: Restrict to an address list — "Only the addresses you list may use the key. The safest choice, and the one to keep." — or Allow from anywhere, which is marked unrestricted and warns that anyone who obtains the secret can spend against it until you notice.
With the list chosen, add rules by address or CIDR block with an action (allow or deny) and a note, and tick Add the next new address automatically if the machine that will use the key does not have a fixed address yet. §5 describes both in full.
IP access is checked before rate limits and budgets, so a blocked caller burns nothing.
3.4 Step 4 — Rate limits
Requests per minute, Max concurrent requests (which protects against a runaway loop in the client), Requests per day and Per-address requests per minute. The last two are optional.
There is deliberately no tokens-per-minute limit. Tokens say little about either cost or load — a cheap model can produce a great many for very little money, and an expensive one a few for a lot — so one number could never be right for both. Spending is bounded by the budgets on the next step and by the vendor key's monthly cap; speed is bounded by the four figures here.
Per-key limits sit under the organisation's aggregate limits from its plan. Clients receive the standard x-ratelimit-* and Retry-After headers, and every refusal is recorded with the limit it hit — which is what lets the Refusals page tell you which of these numbers is set too low (§7).
3.5 Step 5 — Budgets
Five caps in dollars — Per hour, Per day, Per week, Per month, Lifetime — plus Max cost per request. Leave a box empty for no cap on that window. Alert thresholds are ticked, not typed: 50, 75, 80, 90, 95 and 100 % of each cap, and the hint under them says what you have chosen ("Alerts at 50%, 80%, 95% of the cap, once per window", or "No alerts: the cap is enforced silently").
Worst case if this key leaks turns those caps into three figures rather than a sentence: Per day, Per month and From outside the list. The third is $0.00 for a key restricted to an address list and unbounded for one that allows anywhere — which is the number that usually persuades someone to go back a step.
Under them, Vendor key caps this key shares shows a bar per vendor key this key routes through — set under Providers · shared with every key on the same vendor key — so you can see that the $200 monthly cap on openai-production is not this key's alone.
Screenshot to add: wizard step 5 with caps filled in, the three "Worst case if this key leaks" figures, and a shared vendor key cap bar below them.
3.6 Step 6 — Review, and the secret
Review shows what will be created as sections — Identity, Routes and models, IP access, Rate limits, Budgets — each with a Change link back to its step, and the exact request body behind a disclosure for anyone who wants it. Routes and models lists, per provider, the vendor key, its environment, whether the key is pinned to it or on the organisation default, how it is billed, and the models.
Nothing is stored until you press Create key. That press re-checks every step and, if one does not pass, returns you to the first one that fails with the reason at the top.
The new secret is then shown once, with a curl command to verify it and a hint about where to run it from — from an allowed address, from any address, or from the machine whose address will be added if you ticked the capture box. Store it in your secrets manager before closing the dialog: only its hash is kept.
4. Changing a key afterwards
A key's own page carries the same settings as the wizard, on tabs with the same names, so nobody has to hunt for a setting they already filled in once: Overview, Identity, Models & routing, Images, IP access, Rate limits, Budgets, Refusals, Usage, Requests.
The header shows the key's status, its IP mode, a full logging badge where it applies, the masked key (sk-gw-{tenant}-{key id}-••••••••), when it was created, when it expires and when it was last used. Banners appear above it for a suspended key, a revoked key, and a live key that can be used from anywhere.
4.1 The tabs
| Tab | What you change there |
|---|---|
| Overview | Read-only cards: budgets, rate limits, models, images, IP access, vendor key routing, and the client setup snippet. |
| Identity | Name, owner, expiry, environment, request logging and metadata. Save identity. |
| Models & routing | The same per-provider blocks as the wizard's step 2, plus the fallback choice, the two token ceilings and the alias. Save models & routing. |
| Images | The image permission, the ceilings, a separate per-request cost cap and, if you want, a narrower list of image models. Save images. |
| IP access | §5. |
| Rate limits | The four figures. Save rate limits. |
| Budgets | Most one request may cost, the budget table (edit a cap or its thresholds in place, or Remove it) and Add a budget. |
| Refusals | Everything refused for this key (§7.6). |
| Usage, Requests | §9.2 and §9.3. |
Routing and models are one tab, not two, because a route and the models it allows can only be judged together. Moving a key onto a vendor key that allows fewer models used to be possible and only showed up at request time; now the models offered are the ones the chosen vendor key actually allows, and a save that would take models away stops first: Some models would no longer be allowed, listing them, with Save anyway.
4.2 Rotate
Rotate issues a new secret under the same policy and asks how long the current one should keep working, so the legitimate client can be updated: Immediately (old secret stops now), 1 hour, 24 hours or 7 days. The new secret is shown once. The key id does not change, so usage history, budgets and policy carry over — and so does every report and alert that names the key.
Rotating a suspended key invalidates the possibly compromised secret and resumes the key for the new secret only.
4.3 Suspend, resume, revoke
- Suspend is temporary and reversible. Requests receive
403 key_suspended; nothing is forwarded and nothing is spent. Use it when you are not yet sure what is going on. - Resume makes the current secret work again. If the secret may have leaked, rotate instead — the suspended-key banner says so.
- Revoke is permanent, needs the key's name typed to confirm, and takes effect within milliseconds. Usage history is retained.
All three are audited. A key can also be suspended automatically (§5.5) or from a refusal row (§7.4).
5. IP access
Where a key may be used from is the cheapest control there is: it is checked before rate limits and budgets, so a blocked caller burns nothing, and it is the difference between a leaked secret costing money and a leaked secret costing nothing.
5.1 The address list
The key's IP access tab has three cards on the left and the address log on the right.
Where this key may be used from offers the same two cards as the wizard — Restrict to an address list or Allow from anywhere — and a Save that only lights up when the choice has changed. Choosing anywhere shows a red callout: "Unrestricted. Every address on the internet may use this key; only its secret protects your budgets."
Address list is the rules themselves: CIDR, action (allow or deny), how it got there (by hand or added automatically), a note and Remove. The form underneath adds one. A rule takes effect on the next request; both adding and removing are audited.
A list with no rules is not the same as a list that allows everything. With no rules, the organisation's default IP policy decides whether the key works at all — and the default, Require an allowlist, means it does not.
5.2 Add the next new address automatically
The case this exists for: a key shared by several developers whose home connections change address. The key should stay restricted to its list, but when somebody's address changes, nobody wants to look it up, read it out and type it in.
Under the address list, in the Adding the next address card, is one checkbox:
Add the next new address automatically For the next ten minutes, the first address this key is used from is added to the list and the box unticks itself. Exactly one address, once.
Precisely what happens when an owner or admin ticks it:
- A ten-minute window opens, starting when the box is saved (or when the key is created, if it was ticked in the wizard). While it is open the key's page shows how long is left, with the exact time: "Open until 14:12 UTC".
- The first request in that window from an address that is not already on the list is let in, and that address is added as an
allowrule — the exact address for IPv4, and for IPv6 the/64it belongs to, because home IPv6 connections change the second half of their address every day or so while the/64stays put. - The box then unticks itself and the window closes. Only ever one address per tick: a second new address, even a second later, is refused as usual.
- If no new address arrives within ten minutes, the window closes and nothing is added.
- A
denyrule still wins. An address matching one is never added. - Two first requests from different addresses at the same instant cannot both get in; the window is claimed in one database write and the loser is refused.
key.ip_added, and an alert naming the key and the address goes to your alert channels. Whoever calls first in that window gets in — so open it when you know who is about to call, and read the alert when it arrives.Every other address is refused while the window is open, and each attempt appears under Refusals. Ticking the box is allowed even when the key has no rules at all and the organisation requires an allowlist: the first call adds the first address. If that window closes unused, the key refuses everything until an address is added or the box is ticked again.
Once a key has any automatically added address, a second switch appears: Clear automatically added addresses after 30 days unused, on by default. It keeps a changing home connection from leaving a trail of old addresses on the list. Addresses you typed in yourself are never cleared, and each removal is audited.
5.3 Refused addresses, and the one-press Allow
On the right, Addresses seen lists every address this key has been used from — accepted and refused, newest activity first — with how many requests each made, how many were refused, and when it was first and last seen. An address not covered by an allow rule carries an Allow button; one press adds it to the list as an exact-address allow rule noted "from the address log".
This is often the quickest path of all, and it needs no open window: a developer calls, gets a 403, tells you the time, and you allow exactly that address. The same button is on the Refusals page, on any row in the Address group (§7).
Screenshot to add: the IP access tab — the address list with one rule marked added automatically, the Adding the next address card with its window open, and the Addresses seen table with an Allow button on a refused address.
5.4 What the gateway trusts as the client address
The client address is resolved by the platform after its own trusted proxies; forwarded headers from anywhere else are ignored, and an organisation cannot change that.
5.5 Automatic suspension
A key is suspended automatically when it is refused from five different new addresses within an hour. One developer whose address changed, and whose program retries, no longer locks the key for everybody; a key turning up in several places at once still does. The figure is shown on each key's IP access tab and is an organisation setting on the Organisation page (Auto-suspend after denied-IP attempts / hour; leave it empty for the platform default). Resuming a suspended key is one press, and it is audited.
Wrong secrets never suspend a key. A key's id is part of every key and turns up in logs, so anyone who has seen it could otherwise get the key suspended by sending wrong secrets. They raise a key.bad_secret alert and nothing more — guessing a 40-character random secret is not practical.
6. Mail keys
A mail key calls POST /v3/mail/send through your organisation's SendGrid account. It cannot call a model endpoint, and an AI key cannot send mail.
The difference that shapes the whole screen: a mail key is limited by recipients, not requests. One SendGrid call can address up to 1,000 people, so a limit counted in requests would let a leaked key reach 50,000 inboxes in fifty calls without tripping anything.
6.1 Creating one
Choose Mail — SendGrid as the service on step 1 and the wizard becomes four steps: Name & owner, Recipient limits, IP access, Review. There are no models, no token ceilings and no dollar budget — SendGrid sells a plan quota, not tokens.
Recipient limits has four boxes: Maximum recipients per send (refuses a single oversized message outright), Recipients per minute (the one that stops a burst), Recipients per hour and Recipients per day. An empty box means no limit for that window. The wizard refuses a combination that cannot bite — a per-minute limit above the per-hour one, say — and refuses to create a key with no ceiling at all: "A mail key with no ceiling at all is exactly what a leaked key exploits."
Over the limit, the gateway refuses the send outright. Nothing reaches SendGrid, so nothing counts against your account's sending reputation, and the refusal is recorded in the key's send log and under Refusals with the recipients it would have reached.
6.2 The key's page
A mail key's tabs are Overview, Identity, Recipient limits, IP access, Routing, Refusals and Send log.
Routing chooses which of the organisation's SendGrid keys this key sends on — sends then appear under that key in SendGrid's own activity feed. Mail keys follow the same environment rule as AI keys: a development mail key cannot send through the production SendGrid account.
Send log lists every send with its outcome (sent, refused by the gateway, or failed at SendGrid — filterable from the drop-down), the recipient count with the first addresses inline, the subject, the SendGrid message id to search for in SendGrid's own activity feed, the sender and the client address. A row opens the send in full. The message body and attachments are kept only for a key whose request logging is set to record bodies — the same rule a model key's prompt log follows.
7. Refusals
Refusals records every request the gateway refused, or that failed at the vendor: which key, from which address and with which client, when and why. It answers two questions, and the page is laid out as those two questions.
- Is someone using a key that is not theirs? — a key that was lost, leaked, revoked or is being guessed at.
- Are the limits right? — which ones bite, how often, and by how much.
7.1 The filters and the counts
Across the top: a period (1 hour, 24 hours, 7 days), a key drop-down, an Address box, a New addresses only tick, the total ("1,284 refused or failed") and Export CSV, which exports the whole period under the filters you have set rather than the rows on screen.
Under them, six counters that are also filters — press one to narrow the table to it, press it again to clear:
| Group | What lands in it |
|---|---|
| Access — the key itself | A wrong secret for a real key; an old secret used after the rotation grace ended; a revoked, suspended or expired key; a key id this organisation does not have; the wrong kind of key for the endpoint; the organisation suspended or closed. |
| Address — not on the list | The address was not allowed. Flagged new when the key has never worked from it. |
| Limits — rate and concurrency | Requests per minute, per day, per address per minute; too many at once; the organisation's plan-wide limit; a mail recipient limit. |
| Money — budgets and caps | A budget cap, a request too expensive for its per-request cap, a vendor key's monthly cap, the organisation ceiling, prepaid credit exhausted. |
| Request — what was asked | Model not allowed, no such model, invalid request (including a model at the wrong endpoint), an unsupported parameter, a request too large. |
| Vendor — failures upstream | The vendor rate-limited, errored, timed out or was unavailable; no usable vendor key; the operator's key cap; the gateway itself unavailable — with the vendor key used and the vendor's status code. |
7.2 Needs a look
The left-hand card picks out the three things worth acting on, from the same rows the table is showing — nothing is fetched behind your back — with the lost-key cases first and then in order of how often each happened:
- A key that should no longer work anywhere, still being called: "Contractor - AI was revoked and is still being used", or "…is still being called with the secret it had before it was rotated". Marked act now. Someone still has it.
- A key being called with a wrong secret — someone is guessing, or a configuration is broken. An unknown key id is reported one step quieter: "Someone is trying a key id that is not in this organisation".
- A key refused from an address it has never worked from. Marked worth a look.
Each entry gives the address, the client and how many times, and offers Show this address (everything from that address, over seven days, with the other filters dropped), Allow this address where that is the sensible answer, and Open the key.
7.3 Limits being hit
The right-hand card answers the second question, per key and limit: how often it bit in the chosen period, and the peak against the limit — "NewcomerOS Prod - AI · Requests per minute · Peak 180 against a limit of 120" — with a Change link straight to that key's Rate limits tab. A limit that bites thirty times a day is either doing its job or set too low, and this is where you can tell which.
Screenshot to add: the Refusals page with the six group counters, a "Needs a look" entry for a revoked key still in use, and a "Limits being hit" row with its peak.
7.4 The table and a single refusal
The table shows When, Key, Address and client, Why and Times, newest first, up to 200 rows; beyond that the console suggests narrowing the filters or exporting the CSV. The Why column is in plain words — Wrong secret, Address not on the list, Rate limit, Vendor key cap — with the gateway's own message under it.
A row opens a panel with everything recorded about it: when and how many times, which key (name, environment, status), the key id that was presented, the address and whether it is new for that key, the client's User-Agent, the endpoint, the model, the request id, and the numbers behind the refusal — "121st request this minute; the limit is 120", "daily cap $10.00: $9.98 used, this request up to $0.05".
The panel also carries the action that fits the row: Allow this address for an address refusal, Open Rate limits or Open Budgets for a limit or money refusal, Suspend key for an access refusal on a live key, and Everything from this address for any of them. A viewer sees all of it and can export it; the buttons that change something are not offered.
7.5 What is recorded, and what is not
A flood cannot fill the database: at most 60 rows a minute for the same key, address and reason, and at most 600 a minute for the whole organisation, so spreading requests over many addresses does not get round it. Beyond either limit, one row a minute carries the count (and, past the organisation limit, how many distinct addresses were behind it). Rows are kept for 90 days. Requests with no recognisable key at all cannot be tied to any organisation and are counted by the operator instead.
7.6 A single key's refusals
Every key's page has a Refusals tab: the same rows, the same detail panel and the same Export CSV, already narrowed to that key — including requests that presented its id with the wrong secret.
8. Alerts
Alerts has two halves: the channels, and the delivery log.
8.1 Channels
+ Add channel asks for a Type — webhook or email — a target (a URL or an address) and which events it should receive. A webhook channel is given a signing secret, shown once when the channel is created: payloads are JSON signed with HMAC-SHA256 in the X-Gateway-Signature header, and failed deliveries are retried with backoff. The Delivery log lists what was sent where, with the HTTP status and any error, so a webhook that has quietly stopped working is visible.
Removing a channel is immediate: alerts routed only there will no longer be delivered anywhere. An organisation with no channels at all still enforces every cap — it simply does not tell anyone.
8.2 The events
Each event is subscribed to separately, so one webhook can take the security events and an inbox can take the money ones. Refusal-driven alerts are sent at most once an hour per key and reason.
| Event | When it fires |
|---|---|
budget.threshold | A key's budget passed one of its thresholds. |
budget.exhausted | A key's budget is spent. |
credit.threshold | Prepaid credit passed one of its thresholds. |
credit.exhausted | Prepaid credit is gone. |
credit.topup | Credit was added. |
tenant.ceiling | The organisation's monthly ceiling was reached. |
key.autosuspended | A key was suspended automatically (§5.5). |
key.revoked_used | A revoked, suspended or expired key — or the previous secret after a rotation — is still being called. Sent at once, naming the address and the client: "Contractor - AI was revoked on 12 Sep and was used from 198.51.100.23 (curl/8.7.1)". Someone still has it. |
key.bad_secret | Five wrong secrets for one real key within an hour: someone is guessing, or a configuration is broken. |
key.new_address_refused | A key was refused from an address it has never worked from — the first time for each address, with a link to allow it. |
key.ip_added | An address was added by Add the next new address automatically (§5.2), naming the key and the address. |
key.ip_removed | An automatically added address, unused for 30 days, was cleared. |
limits.daily_summary | Once a day: which keys hit which limits, how often, and the peak against the limit, with a link to the key's Rate limits tab. |
vendor.failures | More than ten requests through one vendor key failed at the vendor within ten minutes. |
vendor_key.cap_threshold | A vendor key's monthly cap passed 50, 80 or 95 % (§2.7). |
vendor_key.cap_reached | A vendor key reached its monthly cap. |
support.session | An operator opened or closed a support session on your organisation. |
A new channel starts with budget.threshold, budget.exhausted, credit.threshold, credit.exhausted and key.autosuspended ticked. The three worth adding deliberately are key.revoked_used, key.bad_secret and key.ip_added: they are the ones that tell you a key has got out.
Screenshot to add: the Add alert channel dialog with the type and target filled in and the event list, each event with its one-line explanation.
9. Usage, requests and the audit log
9.1 The dashboard
The dashboard opens on the organisation as a whole, for a period you pick (the buckets are UTC). Five tiles across the top: spend for the period with the change against the previous one, Spend today, Month to date against the monthly ceiling, Prepaid credit and Refused requests.
Under them, one chart over time — switchable between Spend, Requests and Tokens, stacked by provider, with a toggle to read it as a table instead — and then the breakdowns: By model, By key, By provider, How it was paid for (prepaid credit against your own vendor keys), By vendor key, Keys near budget (anything within 20 % of a cap, a click away from its Budgets tab), Refused by an IP rule and Recent alerts. For everything the gateway refused, rather than the IP and budget refusals shown here, go to Refusals (§7).
Screenshot to add: the dashboard with the five tiles, the stacked spend-over-time chart and the breakdown cards below it.
9.2 One key's usage
A key's Usage tab covers Today, 7 days, 30 days or Month to date, with tiles for requests, cost (and cost per request), tokens in and out, and denied requests split by IP and budget; then spend per day and requests per day as bars. Underneath, it names the vendor keys this key's usage is attributable to.
9.3 The request log
The Requests tab is the ledger itself, one row per request: time, model, status, tokens in and out, cost, how it was billed, the vendor key, the client address, latency, whether it streamed, whether a body was stored, and the request id. A row opens the request in full.
What a row contains depends on the key's request logging setting: with metadata only, no prompt or completion text is stored at all. The footer under the table says which of the two this key is on.
9.4 The audit log
Audit log is every change anyone made: when, who (email, or the operator marked as a support session), the action, the target, a summary of what changed from what to what, and the address it came from. There is one filter box across actor, action, target and the change itself.
It is append-only and stored inside your organisation's own database. It is where you go when something is set differently from how you remember leaving it — including addresses added automatically (key.ip_added), the models on a vendor key before and after a narrowing (vendor_key.models), and every operator support session.
10. Money
Five different things bound what an organisation can spend. They are enforced independently, and a request has to satisfy all of them.
10.1 The key's own budgets
Per key: an hourly, daily, weekly, monthly and lifetime cap in dollars, one budget per period. Windows are calendar-aligned in UTC (hour, day, ISO week, month); a lifetime budget never resets. Every request reserves its worst-case cost against them before it is sent, so a cap cannot be overshot by a request already in flight, and the reservation is corrected to the real cost when the answer comes back. Caps are hard-enforced whichever way the request is billed.
Alert thresholds fire once per window, to your alert channels. A budget with no thresholds is enforced silently, which is rarely what anyone wants.
10.2 The per-request cap
Most one request may cost, on the key's Budgets tab. It is checked before the vendor is called, against the worst case the request could reach — the model's price and the maximum tokens it could produce — so a runaway prompt is refused with 402 request_too_expensive and costs nothing. A key that allows image generation can carry a second, separate cap for image requests; when both are set, the lower one applies to an image request.
10.3 The vendor key's monthly cap
The cap described in §2.7, on the vendor key rather than on the virtual key. It is shared by every virtual key routed through that vendor key, which is exactly its point: it bounds what one vendor account can be billed for in a month, however many applications are pointed at it. A request that would cross it is refused with 402 vendor_key_cap_reached, unless the virtual key is set to fall back to the organisation default.
10.4 Prepaid credit and the organisation ceiling
Requests through keys the operator provides are deducted from prepaid credit, shown on the Organisation page with the balance, the top-up history and any pending request. Request a top-up asks for an amount, a payment reference and a note; the operator adds the credit once the payment is received. Requests through your own vendor keys never touch credit.
The Monthly ceiling, also on the Organisation page, is a hard cap across all keys and both ways of paying. It is the number that stops the whole organisation, whatever any individual key's budgets say, and it is the one worth setting first for an organisation that uses its own vendor keys — because those are billed straight to you by the vendor, with no prepaid balance to run out.
10.5 Which of them refused a request
Every one of these refusals is recorded with the figures behind it and appears under Refusals in the Money group, and on the key's own Refusals tab. The detail panel names the cap, what had been used and what this request would have cost — which is usually enough to decide whether the cap is wrong or the caller is.