The low-level Management API surface in supabase is now route-first and intentionally minimal:
supabase api routessupabase api request /v1/projectssupabase api request /v1/projects --method POSTsupabase api request /v1/projects/{ref}/config/auth --schema
The CLI no longer derives a separate public command vocabulary from the OpenAPI document. It keeps the OpenAPI route template as the user-facing identifier, lists discoverable routes directly from the exported spec metadata, resolves the matching operation, and executes the generated api.v1.* client directly.
This keeps ownership simple:
@supabase/apiowns the typed versioned client and operation metadatasupabaseowns route resolution, request UX, and output UX- there is no CLI-side command tree generation, reflection, or operation-name rewriting
The route-first api namespace uses these public @supabase/api exports:
@supabase/api/openapi.jsonopenApiOperationIdMapoperationDefinitionsexecuteApiClientOperation
The OpenAPI snapshot is the metadata source of truth. The typed SDK remains the execution source of truth.
flowchart TD
spec["@supabase/api/openapi.json<br/>raw OpenAPI document"]
join["@supabase/api/effect<br/>openApiOperationIdMap + operationDefinitions + executeApiClientOperation"]
introspect["platform-schema-introspection.ts<br/>OpenAPI request/response schema extraction"]
descriptors["platform-descriptors.ts<br/>OpenAPI operation + SDK operation -> PlatformOperationDescriptor"]
routes["platform-route-resolver.ts<br/>METHOD + route -> descriptor"]
command["api.command.ts<br/>supabase api"]
request["request.command.ts<br/>supabase api request <route>"]
handler["platform-handler.ts<br/>schema / dry-run / confirmation / execution / output"]
ux["platform-input.ts + platform-schema.ts + platform-fields.ts<br/>input parsing, schema payloads, field projection, text rendering"]
spec --> introspect
spec --> descriptors
join --> descriptors
introspect --> descriptors
descriptors --> routes
routes --> request
command --> request
request --> handler
handler --> ux
src/next/commands/platform/api.command.tsDeclares thesupabase apinamespace command and itsroutesandrequestsubcommands.src/next/commands/platform/request.command.tsImplementssupabase api request <route>.src/next/commands/platform/routes.command.tsImplementssupabase api routes.src/next/commands/platform/platform-route-resolver.tsResolves a normalized route template plus optional method into one operation descriptor.src/next/commands/platform/platform-routes.tsDerives the path-level route catalog and text rendering from descriptor metadata.
src/next/commands/platform/platform-openapi.tsLoads@supabase/api/openapi.json, joins raw OpenAPI ids to SDK ids, and exposes normalized operation entries.src/next/commands/platform/platform-schema-introspection.tsConverts raw OpenAPI request and response schemas into CLI request/response schema nodes.src/next/commands/platform/platform-descriptors.tsAssembles the final CLI-facing descriptor model for each route/method pair and binds execution through the API package.src/next/commands/platform/platform-types.tsShared command-local types for descriptors, body kinds, and schema nodes.
src/next/commands/platform/platform-handler.tsShared execution flow for route inspection, dry runs, confirmation, execution, and output.src/next/commands/platform/platform-input.tsParses--params,--json,--body,--body-file, and--upload, prompts for missing values, validates stdin usage, and builds dry-run previews.src/next/commands/platform/platform-schema.tsBuilds the payload returned bysupabase api request <route> --schema.src/next/commands/platform/platform-fields.tsImplements--fieldsprojection and text-mode rendering.src/next/commands/platform/platform-cli.tsSmall route-first formatting helpers used in prompts, examples, and schema guidance.src/next/auth/platform-api.layer.tsWires auth and config into the unified versionedPlatformApiclient.
The request resolver works from the OpenAPI path template itself rather than a derived CLI method name.
Rules:
- Normalize the positional route so both
v1/projectsand/v1/projectswork. - If
--methodis provided, resolve the exactMETHOD + routepair. - If
--methodis omitted and the route has exactly one operation, use it. - If
--methodis omitted and the route supportsGET, default toGET. - Otherwise fail with a clear error listing the supported methods.
This keeps the route template as the public identifier while still giving discovery and execution separate subcommands.
supabase api routes exposes a discovery-first view over the same metadata:
- group routes by OpenAPI
tagsin text output - keep JSON output flat and machine-friendly
- support filtering by:
--group--method--search
The discovery flow is intentionally simple:
supabase api routessupabase api request <route> --schemasupabase api request <route> [--method ...]
Each OpenAPI operation becomes one PlatformOperationDescriptor.
That descriptor keeps:
- operation id
- HTTP method and path template
- available methods for the same route
- short and long descriptions
- request metadata
- response schema
- an
executefunction that decodes input and calls the API-owned generated executor, which in turn dispatches toapi.v1.*
The CLI-specific request model is intentionally smaller than the raw OpenAPI definition:
request.paramsPath, query, and header inputs exposed through--paramsrequest.bodyOne ofnone | json | binary | multipart | urlencoded
supabase api request <route> keeps one consistent flag surface:
--methodSelect the HTTP method when a route exposes multiple operations--paramsNon-body request input as inline JSON, or-for stdin--jsonObject-shaped request bodies--bodyNon-object bodies and raw body content, including JSON arrays/scalars and binary payloads--body-fileFile-backed raw request body input--uploadMultipart binary field input asfield=pathorfield=---fieldsResponse projection--schemaPrint the request and response schema instead of executing--dry-runValidate and preview the request without executing--yesSkip the confirmation prompt for mutating requests
- JSON object body
Use
--json - JSON array or scalar body
Use
--body multipart/form-dataUse--jsonfor structured fields and--uploadfor binary fieldsapplication/x-www-form-urlencodedUse--jsonwith an object; the CLI serializes it as form data- binary or file-like body
Use
--body-fileor--body -for raw bytes
Only one of --params, --json, --body, or --upload may read from stdin in the same invocation.
Two inspection flows are built on top of the same descriptors:
supabase api routesLists discoverable route templates derived from the exported OpenAPI specsupabase api request <route> --schemaReturns the normalized request/response schema and available--fieldsprojectionssupabase api request <route> --dry-runParses, prompts, validates, redacts sensitive values, and previews the outgoing request without executing it
For multi-method routes, include --method whenever you need the non-GET variant or the route does not expose GET.
Examples:
supabase api routes --group projectssupabase api request /v1/projectssupabase api request /v1/projects --method POSTsupabase api request /v1/projects/{ref}/config/auth --method PATCH --schema
When the Management API changes, the normal workflow is:
- Regenerate
@supabase/api - Run the platform metadata and resolver tests
- Update request-shape tests if the endpoint introduces a new body pattern
- Update
api routes/api requestdocs and examples if the endpoint needs bespoke help text
In most cases, no new CLI command file is needed. A new OpenAPI route becomes reachable automatically once:
- it appears in the generated API exports
- its schemas can be introspected into a descriptor
The current route-first coverage is split across a few focused tests:
platform-metadata.unit.test.tsEnsures every exported operation is covered exactly once and verifies route metadata/body kindsplatform-routes.unit.test.tsCovers route discovery, grouping, filtering, help docs, and default method selectionplatform-route-resolver.unit.test.tsCovers route normalization, GET defaulting, sole-method fallback, and ambiguous-route errorsplatform-input.unit.test.tsCovers request merging, prompting, and request-body parsing behaviorprojects-create.integration.test.tsCovers a representative JSON-object route flowplatform-bodies.integration.test.tsCovers JSON array, binary, multipart, and urlencoded bodiesplatform-schema.integration.test.tsCovers schema payload generation
This architecture deliberately keeps the low-level CLI surface boring:
- the public identifier is the OpenAPI route template
- the only execution surface is
api.v1.* - the CLI does not derive or preserve a second management-command namespace
If a future route needs bespoke UX, a hand-written high-level command can still exist separately without complicating the low-level api surface.