From 4ff4cdc62d7265b7dc82020e67a3b46f3f5bd931 Mon Sep 17 00:00:00 2001 From: Hieu Date: Thu, 4 Jun 2026 14:53:26 +0700 Subject: [PATCH] feat: expose mgmt api v2 spec on official document (#46605) ## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Include the v2 mgmt API spec in the official docs. This PR merges the v1 and v2 specs when generating the reference, with v2 taking precedence on conflicts. Fixes API-1215 ## Summary by CodeRabbit * **New Features** * Docs now include API v2 reference: log-drain management (list/create/update/delete) and project transfer (preview/transfer). * **Documentation** * Generated API reference now merges v1 and v2 specs so both appear in the docs and section listings. * New v2 operations added to Analytics and Projects documentation sections. * **Chores** * Docs generation pipeline updated to accept and process multiple API spec inputs. --- .../docs/Reference.generated.script.ts | 23 +- apps/docs/spec/Makefile | 8 +- apps/docs/spec/api_v2_openapi.json | 899 ++++++ apps/docs/spec/common-api-sections.json | 36 + .../spec/sections/generateMgmtApiSections.cts | 146 +- .../transforms/api_v2_openapi_deparsed.json | 2551 +++++++++++++++++ 6 files changed, 3577 insertions(+), 86 deletions(-) create mode 100644 apps/docs/spec/api_v2_openapi.json create mode 100644 apps/docs/spec/transforms/api_v2_openapi_deparsed.json diff --git a/apps/docs/features/docs/Reference.generated.script.ts b/apps/docs/features/docs/Reference.generated.script.ts index d8824206342..7a52c883ffb 100644 --- a/apps/docs/features/docs/Reference.generated.script.ts +++ b/apps/docs/features/docs/Reference.generated.script.ts @@ -17,7 +17,8 @@ import selfHostingRealtimeCommonSections from '~/spec/common-self-hosting-realti import selfHostingStorageCommonSections from '~/spec/common-self-hosting-storage-sections.json' with { type: 'json' } import storageSpec from '~/spec/storage_v0_openapi.json' with { type: 'json' } import analyticsSpec from '~/spec/transforms/analytics_v0_openapi_deparsed.json' with { type: 'json' } -import openApiSpec from '~/spec/transforms/api_v1_openapi_deparsed.json' with { type: 'json' } +import apiV1Spec from '~/spec/transforms/api_v1_openapi_deparsed.json' with { type: 'json' } +import apiV2Spec from '~/spec/transforms/api_v2_openapi_deparsed.json' with { type: 'json' } import { isPlainObject, keyBy } from 'lodash-es' import slugify from 'slugify' import { parse } from 'yaml' @@ -239,7 +240,25 @@ async function writeCliReferenceSections() { } async function writeApiReferenceSections() { - const endpointsById = mapEndpointsById(openApiSpec) + const mergedSpec = { + ...apiV1Spec, + paths: { + ...apiV1Spec.paths, + ...apiV2Spec.paths, + }, + components: { + ...apiV1Spec.components, + schemas: { + ...apiV1Spec.components?.schemas, + ...apiV2Spec.components?.schemas, + }, + securitySchemes: { + ...apiV1Spec.components?.securitySchemes, + ...apiV2Spec.components?.securitySchemes, + }, + }, + } + const endpointsById = mapEndpointsById(mergedSpec) const pendingEndpointsByIdWrite = writeFile( join(GENERATED_DIRECTORY, 'api.latest.endpointsById.json'), JSON.stringify(Array.from(endpointsById.entries())) diff --git a/apps/docs/spec/Makefile b/apps/docs/spec/Makefile index cb598870827..c7e125bffa4 100644 --- a/apps/docs/spec/Makefile +++ b/apps/docs/spec/Makefile @@ -13,7 +13,7 @@ download: download.api.v1 download.storage.v1 download.tsdoc.v2 download.api.v1: curl -sS https://api.supabase.com/api/v1-json > $(REPO_DIR)/api_v1_openapi.json - + curl -sS https://api.supabase.com/api/v2-json > $(REPO_DIR)/api_v2_openapi.json # This flow needs to be updated, so we'l comment out for the moment # Manual flow for now: @@ -58,6 +58,7 @@ transform: dereference.api.v1 dereference.auth.v1 dereference.storage.v0 dereference.api.v1: pnpm exec redocly bundle --dereferenced -o $(REPO_DIR)/transforms/api_v1_openapi_deparsed.json $(REPO_DIR)/api_v1_openapi.json + pnpm exec redocly bundle --dereferenced -o $(REPO_DIR)/transforms/api_v2_openapi_deparsed.json $(REPO_DIR)/api_v2_openapi.json dereference.auth.v1: pnpm exec redocly bundle --dereferenced -o $(REPO_DIR)/transforms/auth_v1_openapi_deparsed.json $(REPO_DIR)/auth_v1_openapi.json @@ -74,7 +75,10 @@ dereference.analytics.v0: generate: generate.sections.api.v1 generate.sections.api.v1: - npx tsx $(REPO_DIR)/sections/generateMgmtApiSections.cts $(REPO_DIR)/transforms/api_v1_openapi_deparsed.json $(REPO_DIR)/common-api-sections.json + npx tsx $(REPO_DIR)/sections/generateMgmtApiSections.cts \ + $(REPO_DIR)/transforms/api_v1_openapi_deparsed.json \ + $(REPO_DIR)/transforms/api_v2_openapi_deparsed.json \ + $(REPO_DIR)/common-api-sections.json ############################################################################### # Validate OpenAPI 3.0 diff --git a/apps/docs/spec/api_v2_openapi.json b/apps/docs/spec/api_v2_openapi.json new file mode 100644 index 00000000000..464289a5721 --- /dev/null +++ b/apps/docs/spec/api_v2_openapi.json @@ -0,0 +1,899 @@ +{ + "openapi": "3.0.0", + "paths": { + "/v2/projects/{ref}/analytics/log-drains": { + "get": { + "operationId": "v2-list-log-drains", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ListLogDrainsResponse" } + } + } + }, + "401": { "description": "Unauthorized" }, + "403": { "description": "Forbidden action" }, + "429": { "description": "Rate limit exceeded" }, + "500": { "description": "Failed to fetch log drains" } + }, + "security": [{ "bearer": [] }, { "fga_permissions": ["analytics_config_read"] }], + "summary": "List project log drains", + "tags": ["Analytics"], + "x-badges": [{ "name": "OAuth scope: analytics_config:read", "position": "after" }], + "x-endpoint-owners": ["analytics"], + "x-oauth-scope": "analytics_config:read" + }, + "post": { + "operationId": "v2-create-log-drain", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/CreateLogDrainRequestOpenApi" } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/LogDrainResponse" } } + } + }, + "401": { "description": "Unauthorized" }, + "402": { + "description": "This feature requires the Pro, Team, or Enterprise organization plan." + }, + "403": { "description": "Forbidden action" }, + "429": { "description": "Rate limit exceeded" }, + "500": { "description": "Failed to create a log drain" } + }, + "security": [{ "bearer": [] }, { "fga_permissions": ["analytics_config_write"] }], + "summary": "Create a log drain for a project", + "tags": ["Analytics"], + "x-allowed-plans": ["Pro", "Team", "Enterprise"], + "x-badges": [ + { "name": "Only available on Pro, Team, Enterprise", "position": "before" }, + { "name": "OAuth scope: analytics_config:write", "position": "after" } + ], + "x-endpoint-owners": ["analytics"], + "x-oauth-scope": "analytics_config:write" + } + }, + "/v2/projects/{ref}/analytics/log-drains/{id}": { + "put": { + "operationId": "v2-update-log-drain", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Log drains identifier", + "schema": { "format": "uuid", "type": "string" } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/UpdateLogDrainRequestOpenApi" } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/LogDrainResponse" } } + } + }, + "401": { "description": "Unauthorized" }, + "403": { "description": "Forbidden action" }, + "429": { "description": "Rate limit exceeded" }, + "500": { "description": "Failed to update log drain" } + }, + "security": [{ "bearer": [] }, { "fga_permissions": ["analytics_config_write"] }], + "summary": "Update a project log drain", + "tags": ["Analytics"], + "x-badges": [{ "name": "OAuth scope: analytics_config:write", "position": "after" }], + "x-endpoint-owners": ["analytics"], + "x-oauth-scope": "analytics_config:write" + }, + "delete": { + "operationId": "v2-delete-log-drain", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Log drains identifier", + "schema": { "format": "uuid", "type": "string" } + } + ], + "responses": { + "204": { "description": "" }, + "401": { "description": "Unauthorized" }, + "403": { "description": "Forbidden action" }, + "429": { "description": "Rate limit exceeded" }, + "500": { "description": "Failed to delete a log drain" } + }, + "security": [{ "bearer": [] }, { "fga_permissions": ["analytics_config_write"] }], + "summary": "Delete a project log drain", + "tags": ["Analytics"], + "x-badges": [{ "name": "OAuth scope: analytics_config:write", "position": "after" }], + "x-endpoint-owners": ["analytics"], + "x-oauth-scope": "analytics_config:write" + } + }, + "/v2/projects/{ref}/transfers/previews": { + "post": { + "operationId": "v2-preview-a-project-transfer", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/V2TransferProjectBody" } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/V2PreviewProjectTransferResponse" } + } + } + }, + "401": { "description": "Unauthorized" }, + "403": { "description": "Forbidden action" }, + "429": { "description": "Rate limit exceeded" } + }, + "security": [{ "bearer": [] }, { "fga_permissions": ["project_admin_read"] }], + "summary": "Previews transferring a project to a different organizations, shows eligibility and impact", + "tags": ["Projects"], + "x-endpoint-owners": ["management-api"] + } + }, + "/v2/projects/{ref}/transfers": { + "post": { + "operationId": "v2-transfer-a-project", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/V2TransferProjectBody" } + } + } + }, + "responses": { + "200": { "description": "" }, + "401": { "description": "Unauthorized" }, + "403": { "description": "Forbidden action" }, + "429": { "description": "Rate limit exceeded" } + }, + "security": [{ "bearer": [] }, { "fga_permissions": ["organization_admin_write"] }], + "summary": "Transfers a project to a different organization", + "tags": ["Projects"], + "x-endpoint-owners": ["management-api"] + } + } + }, + "info": { + "title": "Supabase API (v2)", + "description": "Supabase API generated from the OpenAPI specification.
Visit [https://supabase.com/docs](https://supabase.com/docs) for a complete documentation.", + "version": "1.0.0", + "contact": {} + }, + "tags": [], + "servers": [], + "components": { + "securitySchemes": { "bearer": { "scheme": "bearer", "bearerFormat": "JWT", "type": "http" } }, + "schemas": { + "ListLogDrainsResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["log_drain"], + "description": "Resource type." + }, + "id": { "type": "string" }, + "attributes": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "description": { "type": "string" }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { "type": "string", "nullable": true }, + "schema": { "type": "string" }, + "username": { "type": "string", "nullable": true }, + "password": { "type": "string", "nullable": true }, + "port": { "type": "number", "nullable": true }, + "hostname": { "type": "string" } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { "type": "string" }, + "http": { "type": "string", "enum": ["http1", "http2"] }, + "gzip": { "type": "boolean" }, + "headers": { + "type": "object", + "additionalProperties": { "type": "string" } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { "type": "string" }, + "dataset_id": { "type": "string" } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { "type": "string" }, + "region": { "type": "string" } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { "type": "string" }, + "username": { "type": "string", "nullable": true }, + "password": { "type": "string", "nullable": true }, + "headers": { + "type": "object", + "additionalProperties": { "type": "string" } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { "dsn": { "type": "string" } }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { "type": "string" }, + "api_token": { "type": "string" }, + "dataset_name": { "type": "string" } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { "type": "string" }, + "port": { "type": "integer", "minimum": 0, "maximum": 65535 }, + "tls": { "default": false, "type": "boolean" }, + "structured_data": { "type": "string" }, + "cipher_key": { "type": "string" }, + "ca_cert": { "type": "string" }, + "client_cert": { "type": "string" }, + "client_key": { "type": "string" } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["name", "config", "backend_type"] + } + }, + "required": ["type", "id", "attributes"] + } + } + }, + "required": ["data"] + }, + "CreateLogDrainRequestOpenApi": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { "type": "string", "enum": ["log_drain"], "description": "Resource type." }, + "attributes": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "description": { "type": "string" }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { "type": "string", "nullable": true }, + "schema": { "type": "string" }, + "username": { "type": "string", "nullable": true }, + "password": { "type": "string", "nullable": true }, + "port": { "type": "number", "nullable": true }, + "hostname": { "type": "string" } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { "type": "string" }, + "http": { "type": "string", "enum": ["http1", "http2"] }, + "gzip": { "type": "boolean" }, + "headers": { + "type": "object", + "additionalProperties": { "type": "string" } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { "type": "string" }, + "dataset_id": { "type": "string" } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { "type": "string" }, + "region": { "type": "string" } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { "type": "string" }, + "username": { "type": "string", "nullable": true }, + "password": { "type": "string", "nullable": true }, + "headers": { + "type": "object", + "additionalProperties": { "type": "string" } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { "dsn": { "type": "string" } }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { "type": "string" }, + "api_token": { "type": "string" }, + "dataset_name": { "type": "string" } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { "type": "string" }, + "port": { "type": "integer", "minimum": 0, "maximum": 65535 }, + "tls": { "default": false, "type": "boolean" }, + "structured_data": { "type": "string" }, + "cipher_key": { "type": "string" }, + "ca_cert": { "type": "string" }, + "client_cert": { "type": "string" }, + "client_key": { "type": "string" } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["name", "config", "backend_type"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + }, + "LogDrainResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { "type": "string", "enum": ["log_drain"], "description": "Resource type." }, + "id": { "type": "string" }, + "attributes": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "description": { "type": "string" }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { "type": "string", "nullable": true }, + "schema": { "type": "string" }, + "username": { "type": "string", "nullable": true }, + "password": { "type": "string", "nullable": true }, + "port": { "type": "number", "nullable": true }, + "hostname": { "type": "string" } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { "type": "string" }, + "http": { "type": "string", "enum": ["http1", "http2"] }, + "gzip": { "type": "boolean" }, + "headers": { + "type": "object", + "additionalProperties": { "type": "string" } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { "type": "string" }, + "dataset_id": { "type": "string" } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { "type": "string" }, + "region": { "type": "string" } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { "type": "string" }, + "username": { "type": "string", "nullable": true }, + "password": { "type": "string", "nullable": true }, + "headers": { + "type": "object", + "additionalProperties": { "type": "string" } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { "dsn": { "type": "string" } }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { "type": "string" }, + "api_token": { "type": "string" }, + "dataset_name": { "type": "string" } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { "type": "string" }, + "port": { "type": "integer", "minimum": 0, "maximum": 65535 }, + "tls": { "default": false, "type": "boolean" }, + "structured_data": { "type": "string" }, + "cipher_key": { "type": "string" }, + "ca_cert": { "type": "string" }, + "client_cert": { "type": "string" }, + "client_key": { "type": "string" } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["name", "config", "backend_type"] + } + }, + "required": ["type", "id", "attributes"] + } + }, + "required": ["data"] + }, + "UpdateLogDrainRequestOpenApi": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { "type": "string", "enum": ["log_drain"], "description": "Resource type." }, + "attributes": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "description": { "type": "string" }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { "type": "string", "nullable": true }, + "schema": { "type": "string" }, + "username": { "type": "string", "nullable": true }, + "password": { "type": "string", "nullable": true }, + "port": { "type": "number", "nullable": true }, + "hostname": { "type": "string" } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { "type": "string" }, + "http": { "type": "string", "enum": ["http1", "http2"] }, + "gzip": { "type": "boolean" }, + "headers": { + "type": "object", + "additionalProperties": { "type": "string" } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { "type": "string" }, + "dataset_id": { "type": "string" } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { "type": "string" }, + "region": { "type": "string" } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { "type": "string" }, + "username": { "type": "string", "nullable": true }, + "password": { "type": "string", "nullable": true }, + "headers": { + "type": "object", + "additionalProperties": { "type": "string" } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { "dsn": { "type": "string" } }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { "type": "string" }, + "api_token": { "type": "string" }, + "dataset_name": { "type": "string" } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { "type": "string" }, + "port": { "type": "integer", "minimum": 0, "maximum": 65535 }, + "tls": { "default": false, "type": "boolean" }, + "structured_data": { "type": "string" }, + "cipher_key": { "type": "string" }, + "ca_cert": { "type": "string" }, + "client_cert": { "type": "string" }, + "client_key": { "type": "string" } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["backend_type"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + }, + "V2TransferProjectBody": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["project_transfer_input"], + "description": "Resource type." + }, + "attributes": { + "type": "object", + "properties": { "target_organization_slug": { "type": "string" } }, + "required": ["target_organization_slug"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + }, + "V2PreviewProjectTransferResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["project_transfer_result"], + "description": "Resource type." + }, + "attributes": { + "type": "object", + "properties": { + "valid": { "type": "boolean" }, + "warnings": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { "type": "string" }, + "message": { "type": "string" } + }, + "required": ["key", "message"] + } + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { "type": "string" }, + "message": { "type": "string" } + }, + "required": ["key", "message"] + } + }, + "info": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { "type": "string" }, + "message": { "type": "string" } + }, + "required": ["key", "message"] + } + } + }, + "required": ["valid", "warnings", "errors", "info"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + } + } + } +} diff --git a/apps/docs/spec/common-api-sections.json b/apps/docs/spec/common-api-sections.json index 67e1f055b4a..6d4aad0cd97 100644 --- a/apps/docs/spec/common-api-sections.json +++ b/apps/docs/spec/common-api-sections.json @@ -28,6 +28,18 @@ "type": "category", "title": "Analytics", "items": [ + { + "id": "v2-create-log-drain", + "title": "Create log drain", + "slug": "v2-create-log-drain", + "type": "operation" + }, + { + "id": "v2-delete-log-drain", + "title": "Delete log drain", + "slug": "v2-delete-log-drain", + "type": "operation" + }, { "id": "v1-get-project-function-combined-stats", "title": "Get project function combined stats", @@ -51,6 +63,18 @@ "title": "Get project usage request count", "slug": "v1-get-project-usage-request-count", "type": "operation" + }, + { + "id": "v2-list-log-drains", + "title": "List log drains", + "slug": "v2-list-log-drains", + "type": "operation" + }, + { + "id": "v2-update-log-drain", + "title": "Update log drain", + "slug": "v2-update-log-drain", + "type": "operation" } ] }, @@ -856,12 +880,24 @@ "slug": "v1-pause-a-project", "type": "operation" }, + { + "id": "v2-preview-a-project-transfer", + "title": "Preview a project transfer", + "slug": "v2-preview-a-project-transfer", + "type": "operation" + }, { "id": "v1-restore-a-project", "title": "Restore a project", "slug": "v1-restore-a-project", "type": "operation" }, + { + "id": "v2-transfer-a-project", + "title": "Transfer a project", + "slug": "v2-transfer-a-project", + "type": "operation" + }, { "id": "v1-update-a-project", "title": "Update a project", diff --git a/apps/docs/spec/sections/generateMgmtApiSections.cts b/apps/docs/spec/sections/generateMgmtApiSections.cts index 02deb853df4..ecb55ed9063 100644 --- a/apps/docs/spec/sections/generateMgmtApiSections.cts +++ b/apps/docs/spec/sections/generateMgmtApiSections.cts @@ -3,7 +3,6 @@ import path from 'path' function slugToTitle(slug) { if (!slug) return '' - // remove version prefix if available const prefixRegex = /^v\d+/ const title = slug.replace(prefixRegex, '').replace(/-/g, ' ').trimStart() return title.charAt(0).toUpperCase() + title.slice(1) @@ -14,100 +13,83 @@ function isValidSlug(slug) { return slugRegex.test(slug) } -function extractSectionsFromOpenApi(filePath, outputPath) { - fs.readFile(filePath, 'utf8', (err, data) => { - if (err) { - console.error(`Error reading file ${filePath}:`, err) - return - } +function readJson(filePath: string) { + return JSON.parse(fs.readFileSync(filePath, 'utf8')) +} + +function extractSectionsFromOpenApi(filePaths: string[], outputPath: string) { + try { + // Merge paths from all specs, later specs override earlier ones on conflict + const mergedPaths = Object.assign({}, ...filePaths.map((p) => readJson(p).paths ?? {})) - try { - const openApiJson = JSON.parse(data) - const categories: string[] = [] - const sections: Array<{ + const categories: string[] = [] + const sections: Array<{ + type: string + title: string + id?: string + slug?: string + items: Array<{ type: string title: string - id?: string - slug?: string - items: Array<{ - type: string - title: string - id: string - slug: string - }> - }> = [] + id: string + slug: string + }> + }> = [] - if (openApiJson.paths) { - for (const route in openApiJson.paths) { - const methods = openApiJson.paths[route] - for (const method in methods) { - // We are using `x-internal` to hide endpoints from the docs, - // but still have them included in the spec so they generate types and can be used. - if (methods[method]['x-internal']) { - continue - } - - const tag = methods[method].tags?.[0] - const operationId = methods[method].operationId - // If operationId is not in the form of a slug ignore it. - // This is intentional because operationId is not defined under the swagger - // spec and is extracted automatically from the function name. - if (!tag || !isValidSlug(operationId)) continue - - if (!categories.includes(tag)) { - categories.push(tag) - sections.push({ - type: 'category', - title: tag, - items: [], - }) - } - - const sectionCate = sections.find((i) => i.title === tag) - sectionCate?.items.push({ - id: operationId, - title: slugToTitle(operationId), - slug: operationId, - type: 'operation', - }) - } + for (const route in mergedPaths) { + const methods = mergedPaths[route] + for (const method in methods) { + if (methods[method]['x-internal']) { + continue + } + const tag = methods[method].tags?.[0] + const operationId = methods[method].operationId + if (!tag || !isValidSlug(operationId)) continue + if (!categories.includes(tag)) { + categories.push(tag) + sections.push({ + type: 'category', + title: tag, + items: [], + }) } + const sectionCate = sections.find((i) => i.title === tag) + sectionCate?.items.push({ + id: operationId, + title: slugToTitle(operationId), + slug: operationId, + type: 'operation', + }) } + } - // finalize sections - sections.sort((a, b) => a.title.localeCompare(b.title)) - sections.forEach((i) => i.items.sort((a, b) => a.title.localeCompare(b.title))) - sections.unshift({ - title: 'Introduction', - id: 'introduction', - slug: 'introduction', - type: 'markdown', - items: [], - }) + sections.sort((a, b) => a.title.localeCompare(b.title)) + sections.forEach((i) => i.items.sort((a, b) => a.title.localeCompare(b.title))) + sections.unshift({ + title: 'Introduction', + id: 'introduction', + slug: 'introduction', + type: 'markdown', + items: [], + }) - fs.writeFile(outputPath, JSON.stringify(sections, null, 2), 'utf8', (err) => { - if (err) { - console.error(`Error writing to file ${outputPath}:`, err) - return - } - console.log(`Sections successfully generated!!!`) - }) - } catch (error) { - console.error('Error parsing JSON:', error) - } - }) + fs.writeFileSync(outputPath, JSON.stringify(sections, null, 2), 'utf8') + console.log(`Sections successfully generated!!!`) + } catch (error) { + console.error('Error:', error) + } } -// Get file paths from command line arguments const args = process.argv.slice(2) if (args.length < 2) { - console.error('Please provide the openapi file path and output file path as arguments.') + console.error( + 'Please provide at least one openapi file path and an output file path as arguments.' + ) process.exit(1) } -const inputFilePath = path.resolve(args[0]) -const outputFilePath = path.resolve(args[1]) +// Last arg is output, everything before is input files +const outputFilePath = path.resolve(args[args.length - 1]) +const inputFilePaths = args.slice(0, -1).map((p) => path.resolve(p)) -;(async () => { - extractSectionsFromOpenApi(inputFilePath, outputFilePath) -})() +extractSectionsFromOpenApi(inputFilePaths, outputFilePath) diff --git a/apps/docs/spec/transforms/api_v2_openapi_deparsed.json b/apps/docs/spec/transforms/api_v2_openapi_deparsed.json new file mode 100644 index 00000000000..3e430f5e530 --- /dev/null +++ b/apps/docs/spec/transforms/api_v2_openapi_deparsed.json @@ -0,0 +1,2551 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Supabase API (v2)", + "description": "Supabase API generated from the OpenAPI specification.
Visit [https://supabase.com/docs](https://supabase.com/docs) for a complete documentation.", + "version": "1.0.0", + "contact": {} + }, + "servers": [], + "tags": [], + "paths": { + "/v2/projects/{ref}/analytics/log-drains": { + "get": { + "operationId": "v2-list-log-drains", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["log_drain"], + "description": "Resource type." + }, + "id": { + "type": "string" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true + }, + "schema": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "port": { + "type": "number", + "nullable": true + }, + "hostname": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "http": { + "type": "string", + "enum": ["http1", "http2"] + }, + "gzip": { + "type": "boolean" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { + "type": "string" + }, + "dataset_id": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { + "type": "string" + }, + "region": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { + "dsn": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "api_token": { + "type": "string" + }, + "dataset_name": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "tls": { + "default": false, + "type": "boolean" + }, + "structured_data": { + "type": "string" + }, + "cipher_key": { + "type": "string" + }, + "ca_cert": { + "type": "string" + }, + "client_cert": { + "type": "string" + }, + "client_key": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["name", "config", "backend_type"] + } + }, + "required": ["type", "id", "attributes"] + } + } + }, + "required": ["data"] + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden action" + }, + "429": { + "description": "Rate limit exceeded" + }, + "500": { + "description": "Failed to fetch log drains" + } + }, + "security": [ + { + "bearer": [] + }, + { + "fga_permissions": ["analytics_config_read"] + } + ], + "summary": "List project log drains", + "tags": ["Analytics"], + "x-badges": [ + { + "name": "OAuth scope: analytics_config:read", + "position": "after" + } + ], + "x-endpoint-owners": ["analytics"], + "x-oauth-scope": "analytics_config:read" + }, + "post": { + "operationId": "v2-create-log-drain", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["log_drain"], + "description": "Resource type." + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true + }, + "schema": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "port": { + "type": "number", + "nullable": true + }, + "hostname": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "http": { + "type": "string", + "enum": ["http1", "http2"] + }, + "gzip": { + "type": "boolean" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { + "type": "string" + }, + "dataset_id": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { + "type": "string" + }, + "region": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { + "dsn": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "api_token": { + "type": "string" + }, + "dataset_name": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "tls": { + "default": false, + "type": "boolean" + }, + "structured_data": { + "type": "string" + }, + "cipher_key": { + "type": "string" + }, + "ca_cert": { + "type": "string" + }, + "client_cert": { + "type": "string" + }, + "client_key": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["name", "config", "backend_type"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["log_drain"], + "description": "Resource type." + }, + "id": { + "type": "string" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true + }, + "schema": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "port": { + "type": "number", + "nullable": true + }, + "hostname": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "http": { + "type": "string", + "enum": ["http1", "http2"] + }, + "gzip": { + "type": "boolean" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { + "type": "string" + }, + "dataset_id": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { + "type": "string" + }, + "region": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { + "dsn": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "api_token": { + "type": "string" + }, + "dataset_name": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "tls": { + "default": false, + "type": "boolean" + }, + "structured_data": { + "type": "string" + }, + "cipher_key": { + "type": "string" + }, + "ca_cert": { + "type": "string" + }, + "client_cert": { + "type": "string" + }, + "client_key": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["name", "config", "backend_type"] + } + }, + "required": ["type", "id", "attributes"] + } + }, + "required": ["data"] + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "402": { + "description": "This feature requires the Pro, Team, or Enterprise organization plan." + }, + "403": { + "description": "Forbidden action" + }, + "429": { + "description": "Rate limit exceeded" + }, + "500": { + "description": "Failed to create a log drain" + } + }, + "security": [ + { + "bearer": [] + }, + { + "fga_permissions": ["analytics_config_write"] + } + ], + "summary": "Create a log drain for a project", + "tags": ["Analytics"], + "x-allowed-plans": ["Pro", "Team", "Enterprise"], + "x-badges": [ + { + "name": "Only available on Pro, Team, Enterprise", + "position": "before" + }, + { + "name": "OAuth scope: analytics_config:write", + "position": "after" + } + ], + "x-endpoint-owners": ["analytics"], + "x-oauth-scope": "analytics_config:write" + } + }, + "/v2/projects/{ref}/analytics/log-drains/{id}": { + "put": { + "operationId": "v2-update-log-drain", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Log drains identifier", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["log_drain"], + "description": "Resource type." + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true + }, + "schema": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "port": { + "type": "number", + "nullable": true + }, + "hostname": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "http": { + "type": "string", + "enum": ["http1", "http2"] + }, + "gzip": { + "type": "boolean" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { + "type": "string" + }, + "dataset_id": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { + "type": "string" + }, + "region": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { + "dsn": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "api_token": { + "type": "string" + }, + "dataset_name": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "tls": { + "default": false, + "type": "boolean" + }, + "structured_data": { + "type": "string" + }, + "cipher_key": { + "type": "string" + }, + "ca_cert": { + "type": "string" + }, + "client_cert": { + "type": "string" + }, + "client_key": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["backend_type"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["log_drain"], + "description": "Resource type." + }, + "id": { + "type": "string" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true + }, + "schema": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "port": { + "type": "number", + "nullable": true + }, + "hostname": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "http": { + "type": "string", + "enum": ["http1", "http2"] + }, + "gzip": { + "type": "boolean" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { + "type": "string" + }, + "dataset_id": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { + "type": "string" + }, + "region": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { + "dsn": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "api_token": { + "type": "string" + }, + "dataset_name": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "tls": { + "default": false, + "type": "boolean" + }, + "structured_data": { + "type": "string" + }, + "cipher_key": { + "type": "string" + }, + "ca_cert": { + "type": "string" + }, + "client_cert": { + "type": "string" + }, + "client_key": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["name", "config", "backend_type"] + } + }, + "required": ["type", "id", "attributes"] + } + }, + "required": ["data"] + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden action" + }, + "429": { + "description": "Rate limit exceeded" + }, + "500": { + "description": "Failed to update log drain" + } + }, + "security": [ + { + "bearer": [] + }, + { + "fga_permissions": ["analytics_config_write"] + } + ], + "summary": "Update a project log drain", + "tags": ["Analytics"], + "x-badges": [ + { + "name": "OAuth scope: analytics_config:write", + "position": "after" + } + ], + "x-endpoint-owners": ["analytics"], + "x-oauth-scope": "analytics_config:write" + }, + "delete": { + "operationId": "v2-delete-log-drain", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + }, + { + "name": "id", + "required": true, + "in": "path", + "description": "Log drains identifier", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden action" + }, + "429": { + "description": "Rate limit exceeded" + }, + "500": { + "description": "Failed to delete a log drain" + } + }, + "security": [ + { + "bearer": [] + }, + { + "fga_permissions": ["analytics_config_write"] + } + ], + "summary": "Delete a project log drain", + "tags": ["Analytics"], + "x-badges": [ + { + "name": "OAuth scope: analytics_config:write", + "position": "after" + } + ], + "x-endpoint-owners": ["analytics"], + "x-oauth-scope": "analytics_config:write" + } + }, + "/v2/projects/{ref}/transfers/previews": { + "post": { + "operationId": "v2-preview-a-project-transfer", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["project_transfer_input"], + "description": "Resource type." + }, + "attributes": { + "type": "object", + "properties": { + "target_organization_slug": { + "type": "string" + } + }, + "required": ["target_organization_slug"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["project_transfer_result"], + "description": "Resource type." + }, + "attributes": { + "type": "object", + "properties": { + "valid": { + "type": "boolean" + }, + "warnings": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + }, + "info": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + } + }, + "required": ["valid", "warnings", "errors", "info"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden action" + }, + "429": { + "description": "Rate limit exceeded" + } + }, + "security": [ + { + "bearer": [] + }, + { + "fga_permissions": ["project_admin_read"] + } + ], + "summary": "Previews transferring a project to a different organizations, shows eligibility and impact", + "tags": ["Projects"], + "x-endpoint-owners": ["management-api"] + } + }, + "/v2/projects/{ref}/transfers": { + "post": { + "operationId": "v2-transfer-a-project", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["project_transfer_input"], + "description": "Resource type." + }, + "attributes": { + "type": "object", + "properties": { + "target_organization_slug": { + "type": "string" + } + }, + "required": ["target_organization_slug"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + } + } + } + }, + "responses": { + "200": { + "description": "" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden action" + }, + "429": { + "description": "Rate limit exceeded" + } + }, + "security": [ + { + "bearer": [] + }, + { + "fga_permissions": ["organization_admin_write"] + } + ], + "summary": "Transfers a project to a different organization", + "tags": ["Projects"], + "x-endpoint-owners": ["management-api"] + } + } + }, + "components": { + "securitySchemes": { + "bearer": { + "scheme": "bearer", + "bearerFormat": "JWT", + "type": "http" + } + }, + "schemas": { + "ListLogDrainsResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["log_drain"], + "description": "Resource type." + }, + "id": { + "type": "string" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true + }, + "schema": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "port": { + "type": "number", + "nullable": true + }, + "hostname": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "http": { + "type": "string", + "enum": ["http1", "http2"] + }, + "gzip": { + "type": "boolean" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { + "type": "string" + }, + "dataset_id": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { + "type": "string" + }, + "region": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { + "dsn": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "api_token": { + "type": "string" + }, + "dataset_name": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "tls": { + "default": false, + "type": "boolean" + }, + "structured_data": { + "type": "string" + }, + "cipher_key": { + "type": "string" + }, + "ca_cert": { + "type": "string" + }, + "client_cert": { + "type": "string" + }, + "client_key": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["name", "config", "backend_type"] + } + }, + "required": ["type", "id", "attributes"] + } + } + }, + "required": ["data"] + }, + "CreateLogDrainRequestOpenApi": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["log_drain"], + "description": "Resource type." + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true + }, + "schema": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "port": { + "type": "number", + "nullable": true + }, + "hostname": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "http": { + "type": "string", + "enum": ["http1", "http2"] + }, + "gzip": { + "type": "boolean" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { + "type": "string" + }, + "dataset_id": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { + "type": "string" + }, + "region": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { + "dsn": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "api_token": { + "type": "string" + }, + "dataset_name": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "tls": { + "default": false, + "type": "boolean" + }, + "structured_data": { + "type": "string" + }, + "cipher_key": { + "type": "string" + }, + "ca_cert": { + "type": "string" + }, + "client_cert": { + "type": "string" + }, + "client_key": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["name", "config", "backend_type"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + }, + "LogDrainResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["log_drain"], + "description": "Resource type." + }, + "id": { + "type": "string" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true + }, + "schema": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "port": { + "type": "number", + "nullable": true + }, + "hostname": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "http": { + "type": "string", + "enum": ["http1", "http2"] + }, + "gzip": { + "type": "boolean" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { + "type": "string" + }, + "dataset_id": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { + "type": "string" + }, + "region": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { + "dsn": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "api_token": { + "type": "string" + }, + "dataset_name": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "tls": { + "default": false, + "type": "boolean" + }, + "structured_data": { + "type": "string" + }, + "cipher_key": { + "type": "string" + }, + "ca_cert": { + "type": "string" + }, + "client_cert": { + "type": "string" + }, + "client_key": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["name", "config", "backend_type"] + } + }, + "required": ["type", "id", "attributes"] + } + }, + "required": ["data"] + }, + "UpdateLogDrainRequestOpenApi": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["log_drain"], + "description": "Resource type." + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "config": { + "oneOf": [ + { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true + }, + "schema": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "port": { + "type": "number", + "nullable": true + }, + "hostname": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "postgres" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "http": { + "type": "string", + "enum": ["http1", "http2"] + }, + "gzip": { + "type": "boolean" + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "webhook" + }, + { + "type": "object", + "properties": { + "project_id": { + "type": "string" + }, + "dataset_id": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "bigquery" + }, + { + "type": "object", + "properties": { + "api_key": { + "type": "string" + }, + "region": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "datadog" + }, + { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "username": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "loki" + }, + { + "type": "object", + "properties": { + "dsn": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "sentry" + }, + { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "api_token": { + "type": "string" + }, + "dataset_name": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "axiom" + }, + { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "port": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "tls": { + "default": false, + "type": "boolean" + }, + "structured_data": { + "type": "string" + }, + "cipher_key": { + "type": "string" + }, + "ca_cert": { + "type": "string" + }, + "client_cert": { + "type": "string" + }, + "client_key": { + "type": "string" + } + }, + "additionalProperties": false, + "title": "syslog" + } + ] + }, + "backend_type": { + "type": "string", + "enum": [ + "postgres", + "bigquery", + "clickhouse", + "webhook", + "datadog", + "loki", + "sentry", + "s3", + "axiom", + "last9", + "otlp", + "syslog" + ] + } + }, + "required": ["backend_type"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + }, + "V2TransferProjectBody": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["project_transfer_input"], + "description": "Resource type." + }, + "attributes": { + "type": "object", + "properties": { + "target_organization_slug": { + "type": "string" + } + }, + "required": ["target_organization_slug"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + }, + "V2PreviewProjectTransferResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["project_transfer_result"], + "description": "Resource type." + }, + "attributes": { + "type": "object", + "properties": { + "valid": { + "type": "boolean" + }, + "warnings": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + }, + "info": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + } + }, + "required": ["valid", "warnings", "errors", "info"] + } + }, + "required": ["type", "attributes"] + } + }, + "required": ["data"] + } + } + } +}