OpenAPI (any internal API)¶
Any internal API with an OpenAPI 3 spec. GET only. Reads that look like they return secrets are refused until you say otherwise.
| Policy | openapi/<your-service> |
| Connection kind | openapi |
| Upstream looks like | https://orders.internal.example/api |
| Credential | A read-only API key for your own API, or none |
| Tier | 2 — Prodpeek is the only fence, and the profile says so |
| Time to set up | about 5 minutes |
Grant exactly these¶
- The narrowest read-only key your API can issue
-
Prodpeek only ever sends GET and HEAD, and refuses every other operation the spec describes. If your API can mint a key that cannot write on its own, use it: then two fences hold instead of one.
- No key at all, if the API has no authentication
-
Connect it with the credential header set to
none. Nothing is sent and there is no drop link.
Do not grant these¶
Each of these would undo the point of the rest
An admin or service-owner key
The gateway refuses every write, but a key that can write is one bug in your API's own routing away from a write Prodpeek never saw as one. A GET handler that changes state is more common than it should be.
A key sent as a query parameter
The credential travels in a header you name. A key that only works in the URL ends up in your API's access logs, and Prodpeek does not put it there.
What it does¶
Your spec already says what your API can do. Prodpeek reads it and turns every operation into a tool, then decides each one:
- GET or HEAD becomes an allowed read, with the spec's own enums, required parameters and maximums.
- A parameter named
limit,per_page,page_size,countortopis capped at 200, or lower if the spec says so. - A read that looks like it returns a secret is refused as
read_leaks, with the word named. The words aretoken,secret,password,credential,api_key,private_keyandconnection_string, looked for in the path, the operationId, the summary, the parameters and the response fields. - A GET named like a change (
logout,reset,purge,trigger,delete) is refused aswrite, for you to look at. - POST, PUT, PATCH and DELETE are refused as
write. There is no way to allow one.
An argument the spec does not declare is refused too, rather than sent along.
Step 1: connect it¶
In the console: Services → Connect an internal API from its OpenAPI spec.
Give it a name, the spec URL (or paste the document), and the header your API
reads its key from. Leave the base URL empty to use the spec's servers[0].url.
From an agent:
add_openapi_service name=orders spec_url=https://orders.internal.example/openapi.json auth_header=X-Api-Key
With no credential it returns a drop link for whoever holds the key.
The spec is fetched without a credential. If yours sits behind authentication, paste it instead.
Step 2: read what was generated¶
The policy lands in data/profiles/local/openapi/<name>.yaml, next to the spec
it came from. It is yours to narrow: flip an allow to deny, lower a
maximum. Prodpeek re-reads it on the next restart or refresh.
To accept a read that was refused as read_leaks because you have checked it
does not return a secret, set it to allow, give it tier: 2, and add
override: read_leaks_accepted. The console lists every such override in amber,
and an agent calling prodpeek__explain sees them too.
A profile that allows a non-GET, or an operation the stored spec does not
describe, or a read_leaks read without the override, is refused when it loads.
The service then refuses every call until the file is fixed.
Step 3: when the API changes¶
Press Refresh spec (or call refresh_spec). Your edits are kept. Operations
that disappeared are dropped. New reads arrive refused, noted new since,
so nothing new is reachable before someone has looked at it. A read you allowed
whose operation changed (it became a POST, or started returning a token) goes
back to refused.
Check you got it right¶
- [ ] Test connection lists your GET operations as allowed and every POST, PUT, PATCH and DELETE as refused.
- [ ] Anything listed under 'these reads may return secrets' really does. Leave it refused unless you have checked.
- [ ] The generated profile in data/profiles/local/openapi/
.yaml says verification.status: example.
If an agent is reading this
Call add_openapi_service with the spec URL (or the document) and a service name, and hand the returned drop link to a human for the key. Never ask for the key in chat. If a read you need is refused as read_leaks, tell the human which one and why; only they can accept it, by editing the profile.
Then test it¶
Press Test connection and read the lists: allowed, refused by the policy, and refused because they may return secrets.