Versioning
What the /api/v1 prefix promises, which changes we will not make inside it, and where the OpenAPI document that generates these pages is served.
Every documented operation sits under /api/v1. That prefix is the contract: pin your client to it
and the shapes on these pages stay where they are. A restaurant adds dishes to the menu without
reprinting the prices you already ordered against, and v1 works the same way.
What will not change inside /api/v1
- An operation is not removed, and its path and method stay as they are.
- A field in a response is not removed or renamed, and its type does not change.
- A request field that is optional today does not become required.
- A status code for a condition that already exists does not change, and neither does the
errorcode inside it. - A permission that already lets you do something does not stop letting you do it.
Making any of those means a new prefix, /api/v2, running beside this one.
What can change without notice
- A new operation appears.
- A new field appears in a response body.
- A new optional field is accepted in a request.
- A new
errorcode appears for a condition that had no code before. - Plan ceilings, latency and the order of items in an array.
So read the fields you need and ignore the rest. Treat an error code you do not recognize by its
status: retry a 429 and a 503, fix the request on a 400, fix the credential on a 401 or a 403.
Error codes lists the ones that exist today.
Discovery carries no version
The two documents under /.well-known are unversioned, because the protocol decides their paths.
A relying party takes the iss value out of a token Penv Cloud minted and fetches
{iss}/.well-known/openid-configuration from it, then follows the jwks_uri that document names. A
version segment in the middle would make that derivation fail, so there is none.
https://penv.cloud/.well-known/openid-configuration
https://penv.cloud/.well-known/jwksBoth are public, unauthenticated and cached for 300 seconds. See discovery.
The endpoint your identity provider writes to follows the same rule for the same reason. It lives at
/api/scim/v2/{connectionId}, where v2 is the SCIM protocol's own version and not ours. It is
configured in the console and it is not part of this reference.
The OpenAPI document
https://penv.cloud/openapi.jsonOne JSON document describing every operation on these pages, served from
apps/web/app/openapi.json/route.ts. Point a client generator at it, or read it in an editor that
renders OpenAPI.
Every per-operation page under Secrets, Dynamic, Auth and Discovery is generated from that document, so a parameter or a response on those pages came out of the same source your generated client did. The four pages you are reading now are written by hand.
The document describes the documented surface only. Console, workspace, environment, approval, job, webhook and SCIM endpoints are absent from it on purpose, because they are not a public contract.
Next: secrets.