@lap v0.3
# Machine-readable API spec. Each @endpoint block is one API call.
@api Supabase API (v1)
@version 1.0.0
@auth Bearer bearer
@endpoints 159
@hint download_for_search
@toc branches(8), projects(138), organizations(7), oauth(4), snippets(2)

@group branches
@endpoint GET /v1/branches/{branch_id_or_ref}
@desc Get database branch config
@required {branch_id_or_ref: any # Branch ID}
@returns(200) {ref: str, postgres_version: str, postgres_engine: str, release_channel: str, status: str, db_host: str, db_port: int, db_user: str, db_pass: str, jwt_secret: str}
@errors {500: Failed to retrieve database branch}

@endpoint PATCH /v1/branches/{branch_id_or_ref}
@desc Update database branch config
@required {branch_id_or_ref: any # Branch ID}
@optional {branch_name: str, git_branch: str, reset_on_push: bool # This field is deprecated and will be ignored. Use v1-reset-a-branch endpoint directly instead., persistent: bool, status: str(CREATING_PROJECT/RUNNING_MIGRATIONS/MIGRATIONS_PASSED/MIGRATIONS_FAILED/FUNCTIONS_DEPLOYED/FUNCTIONS_FAILED), request_review: bool, notify_url: str(uri) # HTTP endpoint to receive branch status updates.}
@returns(200) {id: str(uuid), name: str, project_ref: str, parent_project_ref: str, is_default: bool, git_branch: str, pr_number: int(int32), latest_check_run_id: num, persistent: bool, status: str, created_at: str(date-time), updated_at: str(date-time), review_requested_at: str(date-time), with_data: bool, notify_url: str(uri), deletion_scheduled_at: str(date-time), preview_project_status: str}
@errors {500: Failed to update database branch}

@endpoint DELETE /v1/branches/{branch_id_or_ref}
@desc Delete a database branch
@required {branch_id_or_ref: any # Branch ID}
@optional {force: bool=true # If set to false, schedule deletion with 1-hour grace period (only when soft deletion is enabled).}
@returns(200) {message: str}
@errors {500: Failed to delete database branch}

@endpoint POST /v1/branches/{branch_id_or_ref}/push
@desc Pushes a database branch
@required {branch_id_or_ref: any # Branch ID}
@optional {migration_version: str}
@returns(201) {workflow_run_id: str, message: str}
@errors {500: Failed to push database branch}

@endpoint POST /v1/branches/{branch_id_or_ref}/merge
@desc Merges a database branch
@required {branch_id_or_ref: any # Branch ID}
@optional {migration_version: str}
@returns(201) {workflow_run_id: str, message: str}
@errors {500: Failed to merge database branch}

@endpoint POST /v1/branches/{branch_id_or_ref}/reset
@desc Resets a database branch
@required {branch_id_or_ref: any # Branch ID}
@optional {migration_version: str}
@returns(201) {workflow_run_id: str, message: str}
@errors {500: Failed to reset database branch}

@endpoint POST /v1/branches/{branch_id_or_ref}/restore
@desc Restore a scheduled branch deletion
@required {branch_id_or_ref: any # Branch ID}
@returns(200) {message: str}
@errors {500: Failed to restore database branch}

@endpoint GET /v1/branches/{branch_id_or_ref}/diff
@desc [Beta] Diffs a database branch
@required {branch_id_or_ref: any # Branch ID}
@optional {included_schemas: str, pgdelta: bool # Use pg-delta instead of Migra for diffing when true}
@returns(200)
@errors {500: Failed to diff database branch}

@endgroup

@group projects
@endpoint GET /v1/projects
@desc List all projects
@returns(200)

@endpoint POST /v1/projects
@desc Create a project
@required {db_pass: str # Database password, name: str # Name of your project, organization_slug: str # Organization slug}
@optional {organization_id: str # Deprecated: Use `organization_slug` instead., plan: str(free/pro) # Subscription Plan is now set on organization level and is ignored in this request, region: str(us-east-1/us-east-2/us-west-1/us-west-2/ap-east-1/ap-southeast-1/ap-northeast-1/ap-northeast-2/ap-southeast-2/eu-west-1/eu-west-2/eu-west-3/eu-north-1/eu-central-1/eu-central-2/ca-central-1/ap-south-1/sa-east-1) # Region you want your server to reside in. Use region_selection instead., region_selection: any # Region selection. Only one of region or region_selection can be specified., kps_enabled: bool # This field is deprecated and is ignored in this request, desired_instance_size: str(nano/micro/small/medium/large/xlarge/2xlarge/4xlarge/8xlarge/12xlarge/16xlarge/24xlarge/24xlarge_optimized_memory/24xlarge_optimized_cpu/24xlarge_high_memory/48xlarge/48xlarge_optimized_memory/48xlarge_optimized_cpu/48xlarge_high_memory) # Desired instance size. Omit this field to always default to the smallest possible size., template_url: str(uri) # Template URL used to create the project from the CLI.}
@returns(201) {id: str, ref: str, organization_id: str, organization_slug: str, name: str, region: str, created_at: str, status: str}

@endpoint GET /v1/projects/available-regions
@desc [Beta] Gets the list of available regions that can be used for a new project
@required {organization_slug: str # Slug of your organization}
@optional {continent: str(NA/SA/EU/AF/AS/OC/AN) # Continent code to determine regional recommendations: NA (North America), SA (South America), EU (Europe), AF (Africa), AS (Asia), OC (Oceania), AN (Antarctica), desired_instance_size: str(nano/micro/small/medium/large/xlarge/2xlarge/4xlarge/8xlarge/12xlarge/16xlarge/24xlarge/24xlarge_optimized_memory/24xlarge_optimized_cpu/24xlarge_high_memory/48xlarge/48xlarge_optimized_memory/48xlarge_optimized_cpu/48xlarge_high_memory) # Desired instance size. Omit this field to always default to the smallest possible size.}
@returns(200) {recommendations: map{smartGroup: map{name: str, code: str, type: str}, specific: [map]}, all: map{smartGroup: [map], specific: [map]}}

@endgroup

@group organizations
@endpoint GET /v1/organizations
@desc List all organizations
@returns(200)
@errors {500: Unexpected error listing organizations}

@endpoint POST /v1/organizations
@desc Create an organization
@required {name: str}
@returns(201) {id: str, slug: str, name: str}
@errors {500: Unexpected error creating an organization}

@endgroup

@group oauth
@endpoint GET /v1/oauth/authorize
@desc [Beta] Authorize user through oauth
@required {client_id: str(uuid), response_type: str(code/token/id_token token), redirect_uri: str}
@optional {scope: str, state: str, response_mode: str, code_challenge: str, code_challenge_method: str(plain/sha256/S256), organization_slug: str # Organization slug, resource: str(uri) # Resource indicator for MCP (Model Context Protocol) clients}
@returns(204)

@endpoint POST /v1/oauth/token
@desc [Beta] Exchange auth code for user's access and refresh token
@returns(201) {access_token: str, refresh_token: str, expires_in: int, token_type: str}

@endpoint POST /v1/oauth/revoke
@desc [Beta] Revoke oauth app authorization and it's corresponding tokens
@required {client_id: str(uuid), client_secret: str, refresh_token: str}
@returns(204)

@endpoint GET /v1/oauth/authorize/project-claim
@desc Authorize user through oauth and claim a project
@required {project_ref: str # Project ref, client_id: str(uuid), response_type: str(code/token/id_token token), redirect_uri: str}
@optional {state: str, response_mode: str, code_challenge: str, code_challenge_method: str(plain/sha256/S256)}
@returns(204)

@endgroup

@group snippets
@endpoint GET /v1/snippets
@desc Lists SQL snippets for the logged in user
@optional {project_ref: str # Project ref, cursor: str, limit: str, sort_by: str(name/inserted_at), sort_order: str(asc/desc)}
@returns(200) {data: [map], cursor: str}
@errors {500: Failed to list user's SQL snippets}

@endpoint GET /v1/snippets/{id}
@desc Gets a specific SQL snippet
@required {id: str(uuid)}
@returns(200) {id: str, inserted_at: str, updated_at: str, type: str, visibility: str, name: str, description: str?, project: map{id: num, name: str}, owner: map{id: num, username: str}, updated_by: map{id: num, username: str}, favorite: bool, content: map{favorite: bool, schema_version: str, sql: str}}
@errors {500: Failed to retrieve SQL snippet}

@endgroup

@group projects
@endpoint GET /v1/projects/{ref}/actions
@desc List all action runs
@required {ref: str # Project ref}
@optional {offset: num, limit: num}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to list action runs}

@endpoint HEAD /v1/projects/{ref}/actions
@desc Count the number of action runs
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to count action runs}

@endpoint GET /v1/projects/{ref}/actions/{run_id}
@desc Get the status of an action run
@required {ref: str # Project ref, run_id: str # Action Run ID}
@returns(200) {id: str, branch_id: str, run_steps: [map], git_config: any?, workdir: str?, check_run_id: num?, created_at: str, updated_at: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get action run status}

@endpoint PATCH /v1/projects/{ref}/actions/{run_id}/status
@desc Update the status of an action run
@required {ref: str # Project ref, run_id: str # Action Run ID}
@optional {clone: str(CREATED/DEAD/EXITED/PAUSED/REMOVING/RESTARTING/RUNNING), pull: str(CREATED/DEAD/EXITED/PAUSED/REMOVING/RESTARTING/RUNNING), health: str(CREATED/DEAD/EXITED/PAUSED/REMOVING/RESTARTING/RUNNING), configure: str(CREATED/DEAD/EXITED/PAUSED/REMOVING/RESTARTING/RUNNING), migrate: str(CREATED/DEAD/EXITED/PAUSED/REMOVING/RESTARTING/RUNNING), seed: str(CREATED/DEAD/EXITED/PAUSED/REMOVING/RESTARTING/RUNNING), deploy: str(CREATED/DEAD/EXITED/PAUSED/REMOVING/RESTARTING/RUNNING)}
@returns(200) {message: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update action run status}

@endpoint GET /v1/projects/{ref}/actions/{run_id}/logs
@desc Get the logs of an action run
@required {ref: str # Project ref, run_id: str # Action Run ID}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get action run logs}

@endpoint GET /v1/projects/{ref}/api-keys
@desc Get project api keys
@required {ref: str # Project ref}
@optional {reveal: bool # Boolean string, true or false}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint POST /v1/projects/{ref}/api-keys
@desc Creates a new API key for the project
@required {ref: str # Project ref, type: str(publishable/secret), name: str}
@optional {reveal: bool # Boolean string, true or false, description: str, secret_jwt_template: map}
@returns(201) {api_key: str?, id: str?, type: str?, prefix: str?, name: str, description: str?, hash: str?, secret_jwt_template: map?, inserted_at: str(date-time)?, updated_at: str(date-time)?}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/api-keys/legacy
@desc Check whether JWT based legacy (anon, service_role) API keys are enabled. This API endpoint will be removed in the future, check for HTTP 404 Not Found.
@required {ref: str # Project ref}
@returns(200) {enabled: bool}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint PUT /v1/projects/{ref}/api-keys/legacy
@desc Disable or re-enable JWT based legacy (anon, service_role) API keys. This API endpoint will be removed in the future, check for HTTP 404 Not Found.
@required {ref: str # Project ref, enabled: bool # Boolean string, true or false}
@returns(200) {enabled: bool}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint PATCH /v1/projects/{ref}/api-keys/{id}
@desc Updates an API key for the project
@required {ref: str # Project ref, id: str(uuid)}
@optional {reveal: bool # Boolean string, true or false, name: str, description: str, secret_jwt_template: map}
@returns(200) {api_key: str?, id: str?, type: str?, prefix: str?, name: str, description: str?, hash: str?, secret_jwt_template: map?, inserted_at: str(date-time)?, updated_at: str(date-time)?}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/api-keys/{id}
@desc Get API key
@required {ref: str # Project ref, id: str(uuid)}
@optional {reveal: bool # Boolean string, true or false}
@returns(200) {api_key: str?, id: str?, type: str?, prefix: str?, name: str, description: str?, hash: str?, secret_jwt_template: map?, inserted_at: str(date-time)?, updated_at: str(date-time)?}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint DELETE /v1/projects/{ref}/api-keys/{id}
@desc Deletes an API key for the project
@required {ref: str # Project ref, id: str(uuid)}
@optional {reveal: bool # Boolean string, true or false, was_compromised: bool # Boolean string, true or false, reason: str}
@returns(200) {api_key: str?, id: str?, type: str?, prefix: str?, name: str, description: str?, hash: str?, secret_jwt_template: map?, inserted_at: str(date-time)?, updated_at: str(date-time)?}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/branches
@desc List all database branches
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve database branches}

@endpoint POST /v1/projects/{ref}/branches
@desc Create a database branch
@required {ref: str # Project ref, branch_name: str}
@optional {git_branch: str, is_default: bool, persistent: bool, region: str, desired_instance_size: str(pico/nano/micro/small/medium/large/xlarge/2xlarge/4xlarge/8xlarge/12xlarge/16xlarge/24xlarge/24xlarge_optimized_memory/24xlarge_optimized_cpu/24xlarge_high_memory/48xlarge/48xlarge_optimized_memory/48xlarge_optimized_cpu/48xlarge_high_memory), release_channel: str(internal/alpha/beta/ga/withdrawn/preview) # Release channel. If not provided, GA will be used., postgres_engine: str(15/17/17-oriole) # Postgres engine version. If not provided, the latest version will be used., secrets: map, with_data: bool, notify_url: str(uri) # HTTP endpoint to receive branch status updates.}
@returns(201) {id: str(uuid), name: str, project_ref: str, parent_project_ref: str, is_default: bool, git_branch: str, pr_number: int(int32), latest_check_run_id: num, persistent: bool, status: str, created_at: str(date-time), updated_at: str(date-time), review_requested_at: str(date-time), with_data: bool, notify_url: str(uri), deletion_scheduled_at: str(date-time), preview_project_status: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to create database branch}

@endpoint DELETE /v1/projects/{ref}/branches
@desc Disables preview branching
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to disable preview branching}

@endpoint GET /v1/projects/{ref}/branches/{name}
@desc Get a database branch
@required {ref: str # Project ref, name: str}
@returns(200) {id: str(uuid), name: str, project_ref: str, parent_project_ref: str, is_default: bool, git_branch: str, pr_number: int(int32), latest_check_run_id: num, persistent: bool, status: str, created_at: str(date-time), updated_at: str(date-time), review_requested_at: str(date-time), with_data: bool, notify_url: str(uri), deletion_scheduled_at: str(date-time), preview_project_status: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to fetch database branch}

@endpoint GET /v1/projects/{ref}/custom-hostname
@desc [Beta] Gets project's custom hostname config
@required {ref: str # Project ref}
@returns(200) {status: str, custom_hostname: str, data: map{success: bool, errors: [any], messages: [any], result: map{id: str, hostname: str, ssl: map{status: str, validation_records: [map], validation_errors: [map]}, ownership_verification: map{type: str, name: str, value: str}, custom_origin_server: str, verification_errors: [str], status: str}}}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's custom hostname config}

@endpoint DELETE /v1/projects/{ref}/custom-hostname
@desc [Beta] Deletes a project's custom hostname configuration
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to delete project custom hostname configuration}

@endpoint POST /v1/projects/{ref}/custom-hostname/initialize
@desc [Beta] Updates project's custom hostname configuration
@required {ref: str # Project ref, custom_hostname: str}
@returns(201) {status: str, custom_hostname: str, data: map{success: bool, errors: [any], messages: [any], result: map{id: str, hostname: str, ssl: map{status: str, validation_records: [map], validation_errors: [map]}, ownership_verification: map{type: str, name: str, value: str}, custom_origin_server: str, verification_errors: [str], status: str}}}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project custom hostname configuration}

@endpoint POST /v1/projects/{ref}/custom-hostname/reverify
@desc [Beta] Attempts to verify the DNS configuration for project's custom hostname configuration
@required {ref: str # Project ref}
@returns(201) {status: str, custom_hostname: str, data: map{success: bool, errors: [any], messages: [any], result: map{id: str, hostname: str, ssl: map{status: str, validation_records: [map], validation_errors: [map]}, ownership_verification: map{type: str, name: str, value: str}, custom_origin_server: str, verification_errors: [str], status: str}}}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to verify project custom hostname configuration}

@endpoint POST /v1/projects/{ref}/custom-hostname/activate
@desc [Beta] Activates a custom hostname for a project.
@required {ref: str # Project ref}
@returns(201) {status: str, custom_hostname: str, data: map{success: bool, errors: [any], messages: [any], result: map{id: str, hostname: str, ssl: map{status: str, validation_records: [map], validation_errors: [map]}, ownership_verification: map{type: str, name: str, value: str}, custom_origin_server: str, verification_errors: [str], status: str}}}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to activate project custom hostname configuration}

@endpoint GET /v1/projects/{ref}/jit-access
@desc [Beta] Get project's just-in-time access configuration.
@required {ref: str # Project ref}
@returns(200) {user_id: str(uuid), user_roles: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's JIT access config}

@endpoint PUT /v1/projects/{ref}/jit-access
@desc [Beta] Update project's just-in-time access configuration.
@required {ref: str # Project ref, state: str(enabled/disabled/unavailable)}
@returns(200) {user_id: str(uuid), user_roles: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project's just-in-time access configuration.}

@endpoint POST /v1/projects/{ref}/network-bans/retrieve
@desc [Beta] Gets project's network bans
@required {ref: str # Project ref}
@returns(201) {banned_ipv4_addresses: [str]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's network bans}

@endpoint POST /v1/projects/{ref}/network-bans/retrieve/enriched
@desc [Beta] Gets project's network bans with additional information about which databases they affect
@required {ref: str # Project ref}
@returns(201) {banned_ipv4_addresses: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's enriched network bans}

@endpoint DELETE /v1/projects/{ref}/network-bans
@desc [Beta] Remove network bans.
@required {ref: str # Project ref, ipv4_addresses: [str] # List of IP addresses to unban.}
@optional {requester_ip: bool=false # Include requester's public IP in the list of addresses to unban., identifier: str}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to remove network bans.}

@endpoint GET /v1/projects/{ref}/network-restrictions
@desc [Beta] Gets project's network restrictions
@required {ref: str # Project ref}
@returns(200) {entitlement: str, config: map{dbAllowedCidrs: [str], dbAllowedCidrsV6: [str]}, old_config: map{dbAllowedCidrs: [str], dbAllowedCidrsV6: [str]}, status: str, updated_at: str(date-time), applied_at: str(date-time)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's network restrictions}

@endpoint PATCH /v1/projects/{ref}/network-restrictions
@desc [Alpha] Updates project's network restrictions by adding or removing CIDRs
@required {ref: str # Project ref}
@optional {add: map{dbAllowedCidrs: [str], dbAllowedCidrsV6: [str]}, remove: map{dbAllowedCidrs: [str], dbAllowedCidrsV6: [str]}}
@returns(200) {entitlement: str, config: map{dbAllowedCidrs: [map]}, old_config: map{dbAllowedCidrs: [map]}, updated_at: str(date-time), applied_at: str(date-time), status: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project network restrictions}

@endpoint POST /v1/projects/{ref}/network-restrictions/apply
@desc [Beta] Updates project's network restrictions
@required {ref: str # Project ref}
@optional {dbAllowedCidrs: [str], dbAllowedCidrsV6: [str]}
@returns(201) {entitlement: str, config: map{dbAllowedCidrs: [str], dbAllowedCidrsV6: [str]}, old_config: map{dbAllowedCidrs: [str], dbAllowedCidrsV6: [str]}, status: str, updated_at: str(date-time), applied_at: str(date-time)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project network restrictions}

@endpoint GET /v1/projects/{ref}/pgsodium
@desc [Beta] Gets project's pgsodium config
@required {ref: str # Project ref}
@returns(200) {root_key: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's pgsodium config}

@endpoint PUT /v1/projects/{ref}/pgsodium
@desc [Beta] Updates project's pgsodium config. Updating the root_key can cause all data encrypted with the older key to become inaccessible.
@required {ref: str # Project ref, root_key: str}
@returns(200) {root_key: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project's pgsodium config}

@endpoint GET /v1/projects/{ref}/postgrest
@desc Gets project's postgrest config
@required {ref: str # Project ref}
@returns(200) {db_schema: str, max_rows: int, db_extra_search_path: str, db_pool: int?, jwt_secret: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's postgrest config}

@endpoint PATCH /v1/projects/{ref}/postgrest
@desc Updates project's postgrest config
@required {ref: str # Project ref}
@optional {db_extra_search_path: str, db_schema: str, max_rows: int, db_pool: int}
@returns(200) {db_schema: str, max_rows: int, db_extra_search_path: str, db_pool: int?}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project's postgrest config}

@endpoint GET /v1/projects/{ref}
@desc Gets a specific project that belongs to the authenticated user
@required {ref: str # Project ref}
@returns(200) {id: str, ref: str, organization_id: str, organization_slug: str, name: str, region: str, created_at: str, status: str, database: map{host: str, version: str, postgres_engine: str, release_channel: str}}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project}

@endpoint DELETE /v1/projects/{ref}
@desc Deletes the given project
@required {ref: str # Project ref}
@returns(200) {id: int, ref: str, name: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint PATCH /v1/projects/{ref}
@desc Updates the given project
@required {ref: str # Project ref, name: str}
@returns(200) {id: int, ref: str, name: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project}

@endpoint GET /v1/projects/{ref}/secrets
@desc List all secrets
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's secrets}

@endpoint POST /v1/projects/{ref}/secrets
@desc Bulk create secrets
@required {ref: str # Project ref}
@returns(201)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to create project's secrets}

@endpoint DELETE /v1/projects/{ref}/secrets
@desc Bulk delete secrets
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to delete secrets with given names}

@endpoint GET /v1/projects/{ref}/ssl-enforcement
@desc [Beta] Get project's SSL enforcement configuration.
@required {ref: str # Project ref}
@returns(200) {currentConfig: map{database: bool}, appliedSuccessfully: bool}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's SSL enforcement config}

@endpoint PUT /v1/projects/{ref}/ssl-enforcement
@desc [Beta] Update project's SSL enforcement configuration.
@required {ref: str # Project ref, requestedConfig: map{database!: bool}}
@returns(200) {currentConfig: map{database: bool}, appliedSuccessfully: bool}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project's SSL enforcement configuration.}

@endpoint GET /v1/projects/{ref}/types/typescript
@desc Generate TypeScript types
@required {ref: str # Project ref}
@optional {included_schemas: str=public}
@returns(200) {types: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to generate TypeScript types}

@endpoint GET /v1/projects/{ref}/vanity-subdomain
@desc [Beta] Gets current vanity subdomain config
@required {ref: str # Project ref}
@returns(200) {status: str, custom_domain: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get project vanity subdomain configuration}

@endpoint DELETE /v1/projects/{ref}/vanity-subdomain
@desc [Beta] Deletes a project's vanity subdomain configuration
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to delete project vanity subdomain configuration}

@endpoint POST /v1/projects/{ref}/vanity-subdomain/check-availability
@desc [Beta] Checks vanity subdomain availability
@required {ref: str # Project ref, vanity_subdomain: str}
@returns(201) {available: bool}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to check project vanity subdomain configuration}

@endpoint POST /v1/projects/{ref}/vanity-subdomain/activate
@desc [Beta] Activates a vanity subdomain for a project.
@required {ref: str # Project ref, vanity_subdomain: str}
@returns(201) {custom_domain: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to activate project vanity subdomain configuration}

@endpoint POST /v1/projects/{ref}/upgrade
@desc [Beta] Upgrades the project's Postgres version
@required {ref: str # Project ref, target_version: str}
@optional {release_channel: str(internal/alpha/beta/ga/withdrawn/preview)}
@returns(201) {tracking_id: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to initiate project upgrade}

@endpoint GET /v1/projects/{ref}/upgrade/eligibility
@desc [Beta] Returns the project's eligibility for upgrades
@required {ref: str # Project ref}
@returns(200) {eligible: bool, current_app_version: str, current_app_version_release_channel: str, latest_app_version: str, target_upgrade_versions: [map], duration_estimate_hours: num, legacy_auth_custom_roles: [str], objects_to_be_dropped: [str], unsupported_extensions: [str], user_defined_objects_in_internal_schemas: [str], validation_errors: [any]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to determine project upgrade eligibility}

@endpoint GET /v1/projects/{ref}/upgrade/status
@desc [Beta] Gets the latest status of the project's upgrade
@required {ref: str # Project ref}
@optional {tracking_id: str}
@returns(200) {databaseUpgradeStatus: map?{initiated_at: str, latest_status_at: str, target_version: num, error: str, progress: str, status: num}}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project upgrade status}

@endpoint GET /v1/projects/{ref}/readonly
@desc Returns project's readonly mode status
@required {ref: str # Project ref}
@returns(200) {enabled: bool, override_enabled: bool, override_active_until: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get project readonly mode status}

@endpoint POST /v1/projects/{ref}/readonly/temporary-disable
@desc Disables project's readonly mode for the next 15 minutes
@required {ref: str # Project ref}
@returns(201)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to disable project's readonly mode}

@endpoint POST /v1/projects/{ref}/read-replicas/setup
@desc [Beta] Set up a read replica
@required {ref: str # Project ref, read_replica_region: str(us-east-1/us-east-2/us-west-1/us-west-2/ap-east-1/ap-southeast-1/ap-northeast-1/ap-northeast-2/ap-southeast-2/eu-west-1/eu-west-2/eu-west-3/eu-north-1/eu-central-1/eu-central-2/ca-central-1/ap-south-1/sa-east-1) # Region you want your read replica to reside in}
@returns(201)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to set up read replica}

@endpoint POST /v1/projects/{ref}/read-replicas/remove
@desc [Beta] Remove a read replica
@required {ref: str # Project ref, database_identifier: str}
@returns(201)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to remove read replica}

@endpoint GET /v1/projects/{ref}/health
@desc Gets project's service health status
@required {ref: str # Project ref, services: [str]}
@optional {timeout_ms: int}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's service health status}

@endpoint POST /v1/projects/{ref}/config/auth/signing-keys/legacy
@desc Set up the project's existing JWT secret as an in_use JWT signing key. This endpoint will be removed in the future always check for HTTP 404 Not Found.
@required {ref: str # Project ref}
@returns(201) {id: str(uuid), algorithm: str, status: str, public_jwk: any?, created_at: str(date-time), updated_at: str(date-time)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/config/auth/signing-keys/legacy
@desc Get the signing key information for the JWT secret imported as signing key for this project. This endpoint will be removed in the future, check for HTTP 404 Not Found.
@required {ref: str # Project ref}
@returns(200) {id: str(uuid), algorithm: str, status: str, public_jwk: any?, created_at: str(date-time), updated_at: str(date-time)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint POST /v1/projects/{ref}/config/auth/signing-keys
@desc Create a new signing key for the project in standby status
@required {ref: str # Project ref, algorithm: str(EdDSA/ES256/RS256/HS256)}
@optional {status: str(in_use/standby), private_jwk: any}
@returns(201) {id: str(uuid), algorithm: str, status: str, public_jwk: any?, created_at: str(date-time), updated_at: str(date-time)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/config/auth/signing-keys
@desc List all signing keys for the project
@required {ref: str # Project ref}
@returns(200) {keys: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/config/auth/signing-keys/{id}
@desc Get information about a signing key
@required {id: str(uuid), ref: str # Project ref}
@returns(200) {id: str(uuid), algorithm: str, status: str, public_jwk: any?, created_at: str(date-time), updated_at: str(date-time)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint DELETE /v1/projects/{ref}/config/auth/signing-keys/{id}
@desc Remove a signing key from a project. Only possible if the key has been in revoked status for a while.
@required {id: str(uuid), ref: str # Project ref}
@returns(200) {id: str(uuid), algorithm: str, status: str, public_jwk: any?, created_at: str(date-time), updated_at: str(date-time)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint PATCH /v1/projects/{ref}/config/auth/signing-keys/{id}
@desc Update a signing key, mainly its status
@required {id: str(uuid), ref: str # Project ref, status: str(in_use/previously_used/revoked/standby)}
@returns(200) {id: str(uuid), algorithm: str, status: str, public_jwk: any?, created_at: str(date-time), updated_at: str(date-time)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/config/auth
@desc Gets project's auth config
@required {ref: str # Project ref}
@returns(200) {api_max_request_duration: int?, db_max_pool_size: int?, db_max_pool_size_unit: str?, disable_signup: bool?, external_anonymous_users_enabled: bool?, external_apple_additional_client_ids: str?, external_apple_client_id: str?, external_apple_email_optional: bool?, external_apple_enabled: bool?, external_apple_secret: str?, external_azure_client_id: str?, external_azure_email_optional: bool?, external_azure_enabled: bool?, external_azure_secret: str?, external_azure_url: str?, external_bitbucket_client_id: str?, external_bitbucket_email_optional: bool?, external_bitbucket_enabled: bool?, external_bitbucket_secret: str?, external_discord_client_id: str?, external_discord_email_optional: bool?, external_discord_enabled: bool?, external_discord_secret: str?, external_email_enabled: bool?, external_facebook_client_id: str?, external_facebook_email_optional: bool?, external_facebook_enabled: bool?, external_facebook_secret: str?, external_figma_client_id: str?, external_figma_email_optional: bool?, external_figma_enabled: bool?, external_figma_secret: str?, external_github_client_id: str?, external_github_email_optional: bool?, external_github_enabled: bool?, external_github_secret: str?, external_gitlab_client_id: str?, external_gitlab_email_optional: bool?, external_gitlab_enabled: bool?, external_gitlab_secret: str?, external_gitlab_url: str?, external_google_additional_client_ids: str?, external_google_client_id: str?, external_google_email_optional: bool?, external_google_enabled: bool?, external_google_secret: str?, external_google_skip_nonce_check: bool?, external_kakao_client_id: str?, external_kakao_email_optional: bool?, external_kakao_enabled: bool?, external_kakao_secret: str?, external_keycloak_client_id: str?, external_keycloak_email_optional: bool?, external_keycloak_enabled: bool?, external_keycloak_secret: str?, external_keycloak_url: str?, external_linkedin_oidc_client_id: str?, external_linkedin_oidc_email_optional: bool?, external_linkedin_oidc_enabled: bool?, external_linkedin_oidc_secret: str?, external_slack_oidc_client_id: str?, external_slack_oidc_email_optional: bool?, external_slack_oidc_enabled: bool?, external_slack_oidc_secret: str?, external_notion_client_id: str?, external_notion_email_optional: bool?, external_notion_enabled: bool?, external_notion_secret: str?, external_phone_enabled: bool?, external_slack_client_id: str?, external_slack_email_optional: bool?, external_slack_enabled: bool?, external_slack_secret: str?, external_spotify_client_id: str?, external_spotify_email_optional: bool?, external_spotify_enabled: bool?, external_spotify_secret: str?, external_twitch_client_id: str?, external_twitch_email_optional: bool?, external_twitch_enabled: bool?, external_twitch_secret: str?, external_twitter_client_id: str?, external_twitter_email_optional: bool?, external_twitter_enabled: bool?, external_twitter_secret: str?, external_x_client_id: str?, external_x_email_optional: bool?, external_x_enabled: bool?, external_x_secret: str?, external_workos_client_id: str?, external_workos_enabled: bool?, external_workos_secret: str?, external_workos_url: str?, external_web3_solana_enabled: bool?, external_web3_ethereum_enabled: bool?, external_zoom_client_id: str?, external_zoom_email_optional: bool?, external_zoom_enabled: bool?, external_zoom_secret: str?, hook_custom_access_token_enabled: bool?, hook_custom_access_token_uri: str?, hook_custom_access_token_secrets: str?, hook_mfa_verification_attempt_enabled: bool?, hook_mfa_verification_attempt_uri: str?, hook_mfa_verification_attempt_secrets: str?, hook_password_verification_attempt_enabled: bool?, hook_password_verification_attempt_uri: str?, hook_password_verification_attempt_secrets: str?, hook_send_sms_enabled: bool?, hook_send_sms_uri: str?, hook_send_sms_secrets: str?, hook_send_email_enabled: bool?, hook_send_email_uri: str?, hook_send_email_secrets: str?, hook_before_user_created_enabled: bool?, hook_before_user_created_uri: str?, hook_before_user_created_secrets: str?, hook_after_user_created_enabled: bool?, hook_after_user_created_uri: str?, hook_after_user_created_secrets: str?, jwt_exp: int?, mailer_allow_unverified_email_sign_ins: bool?, mailer_autoconfirm: bool?, mailer_otp_exp: int, mailer_otp_length: int?, mailer_secure_email_change_enabled: bool?, mailer_subjects_confirmation: str?, mailer_subjects_email_change: str?, mailer_subjects_invite: str?, mailer_subjects_magic_link: str?, mailer_subjects_reauthentication: str?, mailer_subjects_recovery: str?, mailer_subjects_password_changed_notification: str?, mailer_subjects_email_changed_notification: str?, mailer_subjects_phone_changed_notification: str?, mailer_subjects_mfa_factor_enrolled_notification: str?, mailer_subjects_mfa_factor_unenrolled_notification: str?, mailer_subjects_identity_linked_notification: str?, mailer_subjects_identity_unlinked_notification: str?, mailer_templates_confirmation_content: str?, mailer_templates_email_change_content: str?, mailer_templates_invite_content: str?, mailer_templates_magic_link_content: str?, mailer_templates_reauthentication_content: str?, mailer_templates_recovery_content: str?, mailer_templates_password_changed_notification_content: str?, mailer_templates_email_changed_notification_content: str?, mailer_templates_phone_changed_notification_content: str?, mailer_templates_mfa_factor_enrolled_notification_content: str?, mailer_templates_mfa_factor_unenrolled_notification_content: str?, mailer_templates_identity_linked_notification_content: str?, mailer_templates_identity_unlinked_notification_content: str?, mailer_notifications_password_changed_enabled: bool?, mailer_notifications_email_changed_enabled: bool?, mailer_notifications_phone_changed_enabled: bool?, mailer_notifications_mfa_factor_enrolled_enabled: bool?, mailer_notifications_mfa_factor_unenrolled_enabled: bool?, mailer_notifications_identity_linked_enabled: bool?, mailer_notifications_identity_unlinked_enabled: bool?, mfa_max_enrolled_factors: int?, mfa_totp_enroll_enabled: bool?, mfa_totp_verify_enabled: bool?, mfa_phone_enroll_enabled: bool?, mfa_phone_verify_enabled: bool?, mfa_web_authn_enroll_enabled: bool?, mfa_web_authn_verify_enabled: bool?, mfa_phone_otp_length: int, mfa_phone_template: str?, mfa_phone_max_frequency: int?, nimbus_oauth_client_id: str?, nimbus_oauth_email_optional: bool?, nimbus_oauth_client_secret: str?, password_hibp_enabled: bool?, password_min_length: int?, password_required_characters: str?, rate_limit_anonymous_users: int?, rate_limit_email_sent: int?, rate_limit_sms_sent: int?, rate_limit_token_refresh: int?, rate_limit_verify: int?, rate_limit_otp: int?, rate_limit_web3: int?, refresh_token_rotation_enabled: bool?, saml_enabled: bool?, saml_external_url: str?, saml_allow_encrypted_assertions: bool?, security_sb_forwarded_for_enabled: bool?, security_captcha_enabled: bool?, security_captcha_provider: str?, security_captcha_secret: str?, security_manual_linking_enabled: bool?, security_refresh_token_reuse_interval: int?, security_update_password_require_reauthentication: bool?, sessions_inactivity_timeout: num?, sessions_single_per_user: bool?, sessions_tags: str?, sessions_timebox: num?, site_url: str?, sms_autoconfirm: bool?, sms_max_frequency: int?, sms_messagebird_access_key: str?, sms_messagebird_originator: str?, sms_otp_exp: int?, sms_otp_length: int, sms_provider: str?, sms_template: str?, sms_test_otp: str?, sms_test_otp_valid_until: str(date-time)?, sms_textlocal_api_key: str?, sms_textlocal_sender: str?, sms_twilio_account_sid: str?, sms_twilio_auth_token: str?, sms_twilio_content_sid: str?, sms_twilio_message_service_sid: str?, sms_twilio_verify_account_sid: str?, sms_twilio_verify_auth_token: str?, sms_twilio_verify_message_service_sid: str?, sms_vonage_api_key: str?, sms_vonage_api_secret: str?, sms_vonage_from: str?, smtp_admin_email: str(email)?, smtp_host: str?, smtp_max_frequency: int?, smtp_pass: str?, smtp_port: str?, smtp_sender_name: str?, smtp_user: str?, uri_allow_list: str?, oauth_server_enabled: bool, oauth_server_allow_dynamic_registration: bool, oauth_server_authorization_path: str?, custom_oauth_enabled: bool, custom_oauth_max_providers: int}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's auth config}

@endpoint PATCH /v1/projects/{ref}/config/auth
@desc Updates a project's auth config
@required {ref: str # Project ref}
@optional {site_url: str, disable_signup: bool, jwt_exp: int, smtp_admin_email: str(email), smtp_host: str, smtp_port: str, smtp_user: str, smtp_pass: str, smtp_max_frequency: int, smtp_sender_name: str, mailer_allow_unverified_email_sign_ins: bool, mailer_autoconfirm: bool, mailer_subjects_invite: str, mailer_subjects_confirmation: str, mailer_subjects_recovery: str, mailer_subjects_email_change: str, mailer_subjects_magic_link: str, mailer_subjects_reauthentication: str, mailer_subjects_password_changed_notification: str, mailer_subjects_email_changed_notification: str, mailer_subjects_phone_changed_notification: str, mailer_subjects_mfa_factor_enrolled_notification: str, mailer_subjects_mfa_factor_unenrolled_notification: str, mailer_subjects_identity_linked_notification: str, mailer_subjects_identity_unlinked_notification: str, mailer_templates_invite_content: str, mailer_templates_confirmation_content: str, mailer_templates_recovery_content: str, mailer_templates_email_change_content: str, mailer_templates_magic_link_content: str, mailer_templates_reauthentication_content: str, mailer_templates_password_changed_notification_content: str, mailer_templates_email_changed_notification_content: str, mailer_templates_phone_changed_notification_content: str, mailer_templates_mfa_factor_enrolled_notification_content: str, mailer_templates_mfa_factor_unenrolled_notification_content: str, mailer_templates_identity_linked_notification_content: str, mailer_templates_identity_unlinked_notification_content: str, mailer_notifications_password_changed_enabled: bool, mailer_notifications_email_changed_enabled: bool, mailer_notifications_phone_changed_enabled: bool, mailer_notifications_mfa_factor_enrolled_enabled: bool, mailer_notifications_mfa_factor_unenrolled_enabled: bool, mailer_notifications_identity_linked_enabled: bool, mailer_notifications_identity_unlinked_enabled: bool, mfa_max_enrolled_factors: int, uri_allow_list: str, external_anonymous_users_enabled: bool, external_email_enabled: bool, external_phone_enabled: bool, saml_enabled: bool, saml_external_url: str, security_sb_forwarded_for_enabled: bool, security_captcha_enabled: bool, security_captcha_provider: str(turnstile/hcaptcha), security_captcha_secret: str, sessions_timebox: num, sessions_inactivity_timeout: num, sessions_single_per_user: bool, sessions_tags: str, rate_limit_anonymous_users: int, rate_limit_email_sent: int, rate_limit_sms_sent: int, rate_limit_verify: int, rate_limit_token_refresh: int, rate_limit_otp: int, rate_limit_web3: int, mailer_secure_email_change_enabled: bool, refresh_token_rotation_enabled: bool, password_hibp_enabled: bool, password_min_length: int, password_required_characters: str(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789/abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789/abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\:"|<>?,./`~/), security_manual_linking_enabled: bool, security_update_password_require_reauthentication: bool, security_refresh_token_reuse_interval: int, mailer_otp_exp: int, mailer_otp_length: int, sms_autoconfirm: bool, sms_max_frequency: int, sms_otp_exp: int, sms_otp_length: int, sms_provider: str(messagebird/textlocal/twilio/twilio_verify/vonage), sms_messagebird_access_key: str, sms_messagebird_originator: str, sms_test_otp: str, sms_test_otp_valid_until: str(date-time), sms_textlocal_api_key: str, sms_textlocal_sender: str, sms_twilio_account_sid: str, sms_twilio_auth_token: str, sms_twilio_content_sid: str, sms_twilio_message_service_sid: str, sms_twilio_verify_account_sid: str, sms_twilio_verify_auth_token: str, sms_twilio_verify_message_service_sid: str, sms_vonage_api_key: str, sms_vonage_api_secret: str, sms_vonage_from: str, sms_template: str, hook_mfa_verification_attempt_enabled: bool, hook_mfa_verification_attempt_uri: str, hook_mfa_verification_attempt_secrets: str, hook_password_verification_attempt_enabled: bool, hook_password_verification_attempt_uri: str, hook_password_verification_attempt_secrets: str, hook_custom_access_token_enabled: bool, hook_custom_access_token_uri: str, hook_custom_access_token_secrets: str, hook_send_sms_enabled: bool, hook_send_sms_uri: str, hook_send_sms_secrets: str, hook_send_email_enabled: bool, hook_send_email_uri: str, hook_send_email_secrets: str, hook_before_user_created_enabled: bool, hook_before_user_created_uri: str, hook_before_user_created_secrets: str, hook_after_user_created_enabled: bool, hook_after_user_created_uri: str, hook_after_user_created_secrets: str, external_apple_enabled: bool, external_apple_client_id: str, external_apple_email_optional: bool, external_apple_secret: str, external_apple_additional_client_ids: str, external_azure_enabled: bool, external_azure_client_id: str, external_azure_email_optional: bool, external_azure_secret: str, external_azure_url: str, external_bitbucket_enabled: bool, external_bitbucket_client_id: str, external_bitbucket_email_optional: bool, external_bitbucket_secret: str, external_discord_enabled: bool, external_discord_client_id: str, external_discord_email_optional: bool, external_discord_secret: str, external_facebook_enabled: bool, external_facebook_client_id: str, external_facebook_email_optional: bool, external_facebook_secret: str, external_figma_enabled: bool, external_figma_client_id: str, external_figma_email_optional: bool, external_figma_secret: str, external_github_enabled: bool, external_github_client_id: str, external_github_email_optional: bool, external_github_secret: str, external_gitlab_enabled: bool, external_gitlab_client_id: str, external_gitlab_email_optional: bool, external_gitlab_secret: str, external_gitlab_url: str, external_google_enabled: bool, external_google_client_id: str, external_google_email_optional: bool, external_google_secret: str, external_google_additional_client_ids: str, external_google_skip_nonce_check: bool, external_kakao_enabled: bool, external_kakao_client_id: str, external_kakao_email_optional: bool, external_kakao_secret: str, external_keycloak_enabled: bool, external_keycloak_client_id: str, external_keycloak_email_optional: bool, external_keycloak_secret: str, external_keycloak_url: str, external_linkedin_oidc_enabled: bool, external_linkedin_oidc_client_id: str, external_linkedin_oidc_email_optional: bool, external_linkedin_oidc_secret: str, external_slack_oidc_enabled: bool, external_slack_oidc_client_id: str, external_slack_oidc_email_optional: bool, external_slack_oidc_secret: str, external_notion_enabled: bool, external_notion_client_id: str, external_notion_email_optional: bool, external_notion_secret: str, external_slack_enabled: bool, external_slack_client_id: str, external_slack_email_optional: bool, external_slack_secret: str, external_spotify_enabled: bool, external_spotify_client_id: str, external_spotify_email_optional: bool, external_spotify_secret: str, external_twitch_enabled: bool, external_twitch_client_id: str, external_twitch_email_optional: bool, external_twitch_secret: str, external_twitter_enabled: bool, external_twitter_client_id: str, external_twitter_email_optional: bool, external_twitter_secret: str, external_x_enabled: bool, external_x_client_id: str, external_x_email_optional: bool, external_x_secret: str, external_workos_enabled: bool, external_workos_client_id: str, external_workos_secret: str, external_workos_url: str, external_web3_solana_enabled: bool, external_web3_ethereum_enabled: bool, external_zoom_enabled: bool, external_zoom_client_id: str, external_zoom_email_optional: bool, external_zoom_secret: str, db_max_pool_size: int, db_max_pool_size_unit: str(connections/percent), api_max_request_duration: int, mfa_totp_enroll_enabled: bool, mfa_totp_verify_enabled: bool, mfa_web_authn_enroll_enabled: bool, mfa_web_authn_verify_enabled: bool, mfa_phone_enroll_enabled: bool, mfa_phone_verify_enabled: bool, mfa_phone_max_frequency: int, mfa_phone_otp_length: int, mfa_phone_template: str, nimbus_oauth_client_id: str, nimbus_oauth_client_secret: str, oauth_server_enabled: bool, oauth_server_allow_dynamic_registration: bool, oauth_server_authorization_path: str, custom_oauth_enabled: bool}
@returns(200) {api_max_request_duration: int?, db_max_pool_size: int?, db_max_pool_size_unit: str?, disable_signup: bool?, external_anonymous_users_enabled: bool?, external_apple_additional_client_ids: str?, external_apple_client_id: str?, external_apple_email_optional: bool?, external_apple_enabled: bool?, external_apple_secret: str?, external_azure_client_id: str?, external_azure_email_optional: bool?, external_azure_enabled: bool?, external_azure_secret: str?, external_azure_url: str?, external_bitbucket_client_id: str?, external_bitbucket_email_optional: bool?, external_bitbucket_enabled: bool?, external_bitbucket_secret: str?, external_discord_client_id: str?, external_discord_email_optional: bool?, external_discord_enabled: bool?, external_discord_secret: str?, external_email_enabled: bool?, external_facebook_client_id: str?, external_facebook_email_optional: bool?, external_facebook_enabled: bool?, external_facebook_secret: str?, external_figma_client_id: str?, external_figma_email_optional: bool?, external_figma_enabled: bool?, external_figma_secret: str?, external_github_client_id: str?, external_github_email_optional: bool?, external_github_enabled: bool?, external_github_secret: str?, external_gitlab_client_id: str?, external_gitlab_email_optional: bool?, external_gitlab_enabled: bool?, external_gitlab_secret: str?, external_gitlab_url: str?, external_google_additional_client_ids: str?, external_google_client_id: str?, external_google_email_optional: bool?, external_google_enabled: bool?, external_google_secret: str?, external_google_skip_nonce_check: bool?, external_kakao_client_id: str?, external_kakao_email_optional: bool?, external_kakao_enabled: bool?, external_kakao_secret: str?, external_keycloak_client_id: str?, external_keycloak_email_optional: bool?, external_keycloak_enabled: bool?, external_keycloak_secret: str?, external_keycloak_url: str?, external_linkedin_oidc_client_id: str?, external_linkedin_oidc_email_optional: bool?, external_linkedin_oidc_enabled: bool?, external_linkedin_oidc_secret: str?, external_slack_oidc_client_id: str?, external_slack_oidc_email_optional: bool?, external_slack_oidc_enabled: bool?, external_slack_oidc_secret: str?, external_notion_client_id: str?, external_notion_email_optional: bool?, external_notion_enabled: bool?, external_notion_secret: str?, external_phone_enabled: bool?, external_slack_client_id: str?, external_slack_email_optional: bool?, external_slack_enabled: bool?, external_slack_secret: str?, external_spotify_client_id: str?, external_spotify_email_optional: bool?, external_spotify_enabled: bool?, external_spotify_secret: str?, external_twitch_client_id: str?, external_twitch_email_optional: bool?, external_twitch_enabled: bool?, external_twitch_secret: str?, external_twitter_client_id: str?, external_twitter_email_optional: bool?, external_twitter_enabled: bool?, external_twitter_secret: str?, external_x_client_id: str?, external_x_email_optional: bool?, external_x_enabled: bool?, external_x_secret: str?, external_workos_client_id: str?, external_workos_enabled: bool?, external_workos_secret: str?, external_workos_url: str?, external_web3_solana_enabled: bool?, external_web3_ethereum_enabled: bool?, external_zoom_client_id: str?, external_zoom_email_optional: bool?, external_zoom_enabled: bool?, external_zoom_secret: str?, hook_custom_access_token_enabled: bool?, hook_custom_access_token_uri: str?, hook_custom_access_token_secrets: str?, hook_mfa_verification_attempt_enabled: bool?, hook_mfa_verification_attempt_uri: str?, hook_mfa_verification_attempt_secrets: str?, hook_password_verification_attempt_enabled: bool?, hook_password_verification_attempt_uri: str?, hook_password_verification_attempt_secrets: str?, hook_send_sms_enabled: bool?, hook_send_sms_uri: str?, hook_send_sms_secrets: str?, hook_send_email_enabled: bool?, hook_send_email_uri: str?, hook_send_email_secrets: str?, hook_before_user_created_enabled: bool?, hook_before_user_created_uri: str?, hook_before_user_created_secrets: str?, hook_after_user_created_enabled: bool?, hook_after_user_created_uri: str?, hook_after_user_created_secrets: str?, jwt_exp: int?, mailer_allow_unverified_email_sign_ins: bool?, mailer_autoconfirm: bool?, mailer_otp_exp: int, mailer_otp_length: int?, mailer_secure_email_change_enabled: bool?, mailer_subjects_confirmation: str?, mailer_subjects_email_change: str?, mailer_subjects_invite: str?, mailer_subjects_magic_link: str?, mailer_subjects_reauthentication: str?, mailer_subjects_recovery: str?, mailer_subjects_password_changed_notification: str?, mailer_subjects_email_changed_notification: str?, mailer_subjects_phone_changed_notification: str?, mailer_subjects_mfa_factor_enrolled_notification: str?, mailer_subjects_mfa_factor_unenrolled_notification: str?, mailer_subjects_identity_linked_notification: str?, mailer_subjects_identity_unlinked_notification: str?, mailer_templates_confirmation_content: str?, mailer_templates_email_change_content: str?, mailer_templates_invite_content: str?, mailer_templates_magic_link_content: str?, mailer_templates_reauthentication_content: str?, mailer_templates_recovery_content: str?, mailer_templates_password_changed_notification_content: str?, mailer_templates_email_changed_notification_content: str?, mailer_templates_phone_changed_notification_content: str?, mailer_templates_mfa_factor_enrolled_notification_content: str?, mailer_templates_mfa_factor_unenrolled_notification_content: str?, mailer_templates_identity_linked_notification_content: str?, mailer_templates_identity_unlinked_notification_content: str?, mailer_notifications_password_changed_enabled: bool?, mailer_notifications_email_changed_enabled: bool?, mailer_notifications_phone_changed_enabled: bool?, mailer_notifications_mfa_factor_enrolled_enabled: bool?, mailer_notifications_mfa_factor_unenrolled_enabled: bool?, mailer_notifications_identity_linked_enabled: bool?, mailer_notifications_identity_unlinked_enabled: bool?, mfa_max_enrolled_factors: int?, mfa_totp_enroll_enabled: bool?, mfa_totp_verify_enabled: bool?, mfa_phone_enroll_enabled: bool?, mfa_phone_verify_enabled: bool?, mfa_web_authn_enroll_enabled: bool?, mfa_web_authn_verify_enabled: bool?, mfa_phone_otp_length: int, mfa_phone_template: str?, mfa_phone_max_frequency: int?, nimbus_oauth_client_id: str?, nimbus_oauth_email_optional: bool?, nimbus_oauth_client_secret: str?, password_hibp_enabled: bool?, password_min_length: int?, password_required_characters: str?, rate_limit_anonymous_users: int?, rate_limit_email_sent: int?, rate_limit_sms_sent: int?, rate_limit_token_refresh: int?, rate_limit_verify: int?, rate_limit_otp: int?, rate_limit_web3: int?, refresh_token_rotation_enabled: bool?, saml_enabled: bool?, saml_external_url: str?, saml_allow_encrypted_assertions: bool?, security_sb_forwarded_for_enabled: bool?, security_captcha_enabled: bool?, security_captcha_provider: str?, security_captcha_secret: str?, security_manual_linking_enabled: bool?, security_refresh_token_reuse_interval: int?, security_update_password_require_reauthentication: bool?, sessions_inactivity_timeout: num?, sessions_single_per_user: bool?, sessions_tags: str?, sessions_timebox: num?, site_url: str?, sms_autoconfirm: bool?, sms_max_frequency: int?, sms_messagebird_access_key: str?, sms_messagebird_originator: str?, sms_otp_exp: int?, sms_otp_length: int, sms_provider: str?, sms_template: str?, sms_test_otp: str?, sms_test_otp_valid_until: str(date-time)?, sms_textlocal_api_key: str?, sms_textlocal_sender: str?, sms_twilio_account_sid: str?, sms_twilio_auth_token: str?, sms_twilio_content_sid: str?, sms_twilio_message_service_sid: str?, sms_twilio_verify_account_sid: str?, sms_twilio_verify_auth_token: str?, sms_twilio_verify_message_service_sid: str?, sms_vonage_api_key: str?, sms_vonage_api_secret: str?, sms_vonage_from: str?, smtp_admin_email: str(email)?, smtp_host: str?, smtp_max_frequency: int?, smtp_pass: str?, smtp_port: str?, smtp_sender_name: str?, smtp_user: str?, uri_allow_list: str?, oauth_server_enabled: bool, oauth_server_allow_dynamic_registration: bool, oauth_server_authorization_path: str?, custom_oauth_enabled: bool, custom_oauth_max_providers: int}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project's auth config}

@endpoint POST /v1/projects/{ref}/config/auth/third-party-auth
@desc Creates a new third-party auth integration
@required {ref: str # Project ref}
@optional {oidc_issuer_url: str, jwks_url: str, custom_jwks: any}
@returns(201) {id: str(uuid), type: str, oidc_issuer_url: str?, jwks_url: str?, custom_jwks: any?, resolved_jwks: any?, inserted_at: str, updated_at: str, resolved_at: str?}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/config/auth/third-party-auth
@desc Lists all third-party auth integrations
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint DELETE /v1/projects/{ref}/config/auth/third-party-auth/{tpa_id}
@desc Removes a third-party auth integration
@required {ref: str # Project ref, tpa_id: str(uuid)}
@returns(200) {id: str(uuid), type: str, oidc_issuer_url: str?, jwks_url: str?, custom_jwks: any?, resolved_jwks: any?, inserted_at: str, updated_at: str, resolved_at: str?}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/config/auth/third-party-auth/{tpa_id}
@desc Get a third-party integration
@required {ref: str # Project ref, tpa_id: str(uuid)}
@returns(200) {id: str(uuid), type: str, oidc_issuer_url: str?, jwks_url: str?, custom_jwks: any?, resolved_jwks: any?, inserted_at: str, updated_at: str, resolved_at: str?}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint POST /v1/projects/{ref}/pause
@desc Pauses the given project
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/restore
@desc Lists available restore versions for the given project
@required {ref: str # Project ref}
@returns(200) {available_versions: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint POST /v1/projects/{ref}/restore
@desc Restores the given project
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint POST /v1/projects/{ref}/restore/cancel
@desc Cancels the given project restoration
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/billing/addons
@desc List billing addons and compute instance selections
@required {ref: str # Project ref}
@returns(200) {selected_addons: [map], available_addons: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to list project addons}

@endpoint PATCH /v1/projects/{ref}/billing/addons
@desc Apply or update billing addons, including compute instance size
@required {ref: str # Project ref, addon_variant: any, addon_type: str(custom_domain/compute_instance/pitr/ipv4/auth_mfa_phone/auth_mfa_web_authn/log_drain)}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to apply project addon}

@endpoint DELETE /v1/projects/{ref}/billing/addons/{addon_variant}
@desc Remove billing addons or revert compute instance sizing
@required {ref: str # Project ref, addon_variant: any}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to remove project addon}

@endpoint GET /v1/projects/{ref}/claim-token
@desc Gets project claim token
@required {ref: str # Project ref}
@returns(200) {token_alias: str, expires_at: str, created_at: str, created_by: str(uuid)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint POST /v1/projects/{ref}/claim-token
@desc Creates project claim token
@required {ref: str # Project ref}
@returns(200) {token: str, token_alias: str, expires_at: str, created_at: str, created_by: str(uuid)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint DELETE /v1/projects/{ref}/claim-token
@desc Revokes project claim token
@required {ref: str # Project ref}
@returns(204)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/advisors/performance
@desc Gets project performance advisors.
@required {ref: str # Project ref}
@returns(200) {lints: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/advisors/security
@desc Gets project security advisors.
@required {ref: str # Project ref}
@optional {lint_type: str}
@returns(200) {lints: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/analytics/endpoints/logs.all
@desc Gets project's logs
@required {ref: str # Project ref}
@optional {sql: str # Custom SQL query to execute on the logs. See [querying logs](/docs/guides/telemetry/logs?queryGroups=product&product=postgres&queryGroups=source&source=edge_logs#querying-with-the-logs-explorer) for more details., iso_timestamp_start: str(date-time), iso_timestamp_end: str(date-time)}
@returns(200) {result: [any], error: any}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/analytics/endpoints/usage.api-counts
@desc Gets project's usage api counts
@required {ref: str # Project ref}
@optional {interval: str(15min/30min/1hr/3hr/1day/3day/7day)}
@returns(200) {result: [map], error: any}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get project's usage api counts}

@endpoint GET /v1/projects/{ref}/analytics/endpoints/usage.api-requests-count
@desc Gets project's usage api requests count
@required {ref: str # Project ref}
@returns(200) {result: [map], error: any}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get project's usage api requests count}

@endpoint GET /v1/projects/{ref}/analytics/endpoints/functions.combined-stats
@desc Gets a project's function combined statistics
@required {ref: str # Project ref, interval: str(15min/1hr/3hr/1day), function_id: str}
@returns(200) {result: [any], error: any}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get project's function combined statistics}

@endpoint POST /v1/projects/{ref}/cli/login-role
@desc [Beta] Create a login role for CLI with temporary password
@required {ref: str # Project ref, read_only: bool}
@returns(201) {role: str, password: str, ttl_seconds: int(int64)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to create login role}

@endpoint DELETE /v1/projects/{ref}/cli/login-role
@desc [Beta] Delete existing login roles used by CLI
@required {ref: str # Project ref}
@returns(200) {message: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to delete login roles}

@endpoint GET /v1/projects/{ref}/database/migrations
@desc List applied migration versions
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to list database migrations}

@endpoint POST /v1/projects/{ref}/database/migrations
@desc Apply a database migration
@required {ref: str # Project ref, query: str}
@optional {Idempotency-Key: str # A unique key to ensure the same migration is tracked only once., name: str, rollback: str}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to apply database migration}

@endpoint PUT /v1/projects/{ref}/database/migrations
@desc Upsert a database migration without applying
@required {ref: str # Project ref, query: str}
@optional {Idempotency-Key: str # A unique key to ensure the same migration is tracked only once., name: str, rollback: str}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to upsert database migration}

@endpoint DELETE /v1/projects/{ref}/database/migrations
@desc Rollback database migrations and remove them from history table
@required {ref: str # Project ref, gte: str # Rollback migrations greater or equal to this version}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to rollback database migration}

@endpoint GET /v1/projects/{ref}/database/migrations/{version}
@desc Fetch an existing entry from migration history
@required {ref: str # Project ref, version: str}
@returns(200) {version: str, name: str, statements: [str], rollback: [str], created_by: str, idempotency_key: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get database migration}

@endpoint PATCH /v1/projects/{ref}/database/migrations/{version}
@desc Patch an existing entry in migration history
@required {ref: str # Project ref, version: str}
@optional {name: str, rollback: str}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to patch database migration}

@endpoint POST /v1/projects/{ref}/database/query
@desc [Beta] Run sql query
@required {ref: str # Project ref, query: str}
@optional {parameters: [any], read_only: bool}
@returns(201)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to run sql query}

@endpoint POST /v1/projects/{ref}/database/query/read-only
@desc [Beta] Run a sql query as supabase_read_only_user
@required {ref: str # Project ref, query: str}
@optional {parameters: [any]}
@returns(201)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to run read-only sql query}

@endpoint POST /v1/projects/{ref}/database/webhooks/enable
@desc [Beta] Enables Database Webhooks on the project
@required {ref: str # Project ref}
@returns(201)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to enable Database Webhooks on the project}

@endpoint GET /v1/projects/{ref}/database/context
@desc Gets database metadata for the given project.
@required {ref: str # Project ref}
@returns(200) {databases: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint PATCH /v1/projects/{ref}/database/password
@desc Updates the database password
@required {ref: str # Project ref, password: str}
@returns(200) {message: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update database password}

@endpoint GET /v1/projects/{ref}/database/jit
@desc Get user-id to role mappings for JIT access
@required {ref: str # Project ref}
@returns(200) {user_id: str(uuid), user_roles: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to list database jit access}

@endpoint POST /v1/projects/{ref}/database/jit
@desc Authorize user-id to role mappings for JIT access
@required {ref: str # Project ref, role: str, rhost: str}
@returns(200) {user_id: str(uuid), user_role: map{role: str, expires_at: num, allowed_networks: map{allowed_cidrs: [map], allowed_cidrs_v6: [map]}}}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to authorize database jit access}

@endpoint PUT /v1/projects/{ref}/database/jit
@desc Updates a user mapping for JIT access
@required {ref: str # Project ref, user_id: str(uuid), roles: [map{role!: str, expires_at: num, allowed_networks: map}]}
@returns(200) {user_id: str(uuid), user_roles: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to upsert database migration}

@endpoint GET /v1/projects/{ref}/database/jit/list
@desc List all user-id to role mappings for JIT access
@required {ref: str # Project ref}
@returns(200) {items: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to list database jit access}

@endpoint DELETE /v1/projects/{ref}/database/jit/{user_id}
@desc Delete JIT access by user-id
@required {ref: str # Project ref, user_id: str(uuid)}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to remove JIT access}

@endpoint GET /v1/projects/{ref}/database/openapi
@desc Get PostgREST OpenAPI spec
@required {ref: str # Project ref}
@optional {schema: str=public # The database schema to generate the OpenAPI spec for}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to fetch PostgREST OpenAPI spec}

@endpoint GET /v1/projects/{ref}/functions
@desc List all functions
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's functions}

@endpoint POST /v1/projects/{ref}/functions
@desc Create a function
@required {ref: str # Project ref, slug: str, name: str, body: str}
@optional {slug: str, name: str, verify_jwt: bool # Boolean string, true or false, import_map: bool # Boolean string, true or false, entrypoint_path: str, import_map_path: str, ezbr_sha256: str, verify_jwt: bool}
@returns(201) {id: str, slug: str, name: str, status: str, version: int, created_at: int(int64), updated_at: int(int64), verify_jwt: bool, import_map: bool, entrypoint_path: str, import_map_path: str, ezbr_sha256: str}
@errors {401: Unauthorized, 402: Maximum number of functions reached for Plan, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to create project's function}

@endpoint PUT /v1/projects/{ref}/functions
@desc Bulk update functions
@required {ref: str # Project ref}
@returns(200) {functions: [map]}
@errors {401: Unauthorized, 402: Maximum number of functions reached for Plan, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update functions}

@endpoint POST /v1/projects/{ref}/functions/deploy
@desc Deploy a function
@required {ref: str # Project ref}
@optional {slug: str, bundleOnly: bool # Boolean string, true or false}
@returns(201) {id: str, slug: str, name: str, status: str, version: int, created_at: int(int64), updated_at: int(int64), verify_jwt: bool, import_map: bool, entrypoint_path: str, import_map_path: str, ezbr_sha256: str}
@errors {401: Unauthorized, 402: Maximum number of functions reached for Plan, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to deploy function}

@endpoint GET /v1/projects/{ref}/functions/{function_slug}
@desc Retrieve a function
@required {ref: str # Project ref, function_slug: str # Function slug}
@returns(200) {id: str, slug: str, name: str, status: str, version: int, created_at: int(int64), updated_at: int(int64), verify_jwt: bool, import_map: bool, entrypoint_path: str, import_map_path: str, ezbr_sha256: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve function with given slug}

@endpoint PATCH /v1/projects/{ref}/functions/{function_slug}
@desc Update a function
@required {ref: str # Project ref, function_slug: str # Function slug}
@optional {slug: str, name: str, verify_jwt: bool # Boolean string, true or false, import_map: bool # Boolean string, true or false, entrypoint_path: str, import_map_path: str, ezbr_sha256: str, name: str, body: str, verify_jwt: bool}
@returns(200) {id: str, slug: str, name: str, status: str, version: int, created_at: int(int64), updated_at: int(int64), verify_jwt: bool, import_map: bool, entrypoint_path: str, import_map_path: str, ezbr_sha256: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update function with given slug}

@endpoint DELETE /v1/projects/{ref}/functions/{function_slug}
@desc Delete a function
@required {ref: str # Project ref, function_slug: str # Function slug}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to delete function with given slug}

@endpoint GET /v1/projects/{ref}/functions/{function_slug}/body
@desc Retrieve a function body
@required {ref: str # Project ref, function_slug: str # Function slug}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve function body with given slug}

@endpoint GET /v1/projects/{ref}/storage/buckets
@desc Lists all buckets
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get list of buckets}

@endpoint GET /v1/projects/{ref}/config/disk
@desc Get database disk attributes
@required {ref: str # Project ref}
@returns(200) {attributes: any, last_modified_at: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get database disk attributes}

@endpoint POST /v1/projects/{ref}/config/disk
@desc Modify database disk
@required {ref: str # Project ref, attributes: any}
@returns(201)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to modify database disk}

@endpoint GET /v1/projects/{ref}/config/disk/util
@desc Get disk utilization
@required {ref: str # Project ref}
@returns(200) {timestamp: str, metrics: map{fs_size_bytes: num, fs_avail_bytes: num, fs_used_bytes: num}}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get disk utilization}

@endpoint GET /v1/projects/{ref}/config/disk/autoscale
@desc Gets project disk autoscale config
@required {ref: str # Project ref}
@returns(200) {growth_percent: int?, min_increment_gb: int?, max_size_gb: int?}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get project disk autoscale config}

@endpoint GET /v1/projects/{ref}/config/storage
@desc Gets project's storage config
@required {ref: str # Project ref}
@returns(200) {fileSizeLimit: int(int64), features: map{imageTransformation: map{enabled: bool}, s3Protocol: map{enabled: bool}, icebergCatalog: map{enabled: bool, maxNamespaces: int, maxTables: int, maxCatalogs: int}, vectorBuckets: map{enabled: bool, maxBuckets: int, maxIndexes: int}}, capabilities: map{list_v2: bool, iceberg_catalog: bool}, external: map{upstreamTarget: str}, migrationVersion: str, databasePoolMode: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's storage config}

@endpoint PATCH /v1/projects/{ref}/config/storage
@desc Updates project's storage config
@required {ref: str # Project ref}
@optional {fileSizeLimit: int(int64), features: map{imageTransformation: map, s3Protocol: map, icebergCatalog: map, vectorBuckets: map}, external: map{upstreamTarget!: str}}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project's storage config}

@endpoint GET /v1/projects/{ref}/config/database/pgbouncer
@desc Get project's pgbouncer config
@required {ref: str # Project ref}
@returns(200) {default_pool_size: int, ignore_startup_parameters: str, max_client_conn: int, pool_mode: str, connection_string: str, server_idle_timeout: int, server_lifetime: int, query_wait_timeout: int, reserve_pool_size: int}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's pgbouncer config}

@endpoint GET /v1/projects/{ref}/config/database/pooler
@desc Gets project's supavisor config
@required {ref: str # Project ref}
@returns(200)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's supavisor config}

@endpoint PATCH /v1/projects/{ref}/config/database/pooler
@desc Updates project's supavisor config
@required {ref: str # Project ref}
@optional {default_pool_size: int, pool_mode: str(transaction/session) # Dedicated pooler mode for the project}
@returns(200) {default_pool_size: int?, pool_mode: str}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project's supavisor config}

@endpoint GET /v1/projects/{ref}/config/database/postgres
@desc Gets project's Postgres config
@required {ref: str # Project ref}
@returns(200) {effective_cache_size: str, logical_decoding_work_mem: str, maintenance_work_mem: str, track_activity_query_size: str, max_connections: int, max_locks_per_transaction: int, max_parallel_maintenance_workers: int, max_parallel_workers: int, max_parallel_workers_per_gather: int, max_replication_slots: int, max_slot_wal_keep_size: str, max_standby_archive_delay: str, max_standby_streaming_delay: str, max_wal_size: str, max_wal_senders: int, max_worker_processes: int, session_replication_role: str, shared_buffers: str, statement_timeout: str, track_commit_timestamp: bool, wal_keep_size: str, wal_sender_timeout: str, work_mem: str, checkpoint_timeout: str, hot_standby_feedback: bool}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to retrieve project's Postgres config}

@endpoint PUT /v1/projects/{ref}/config/database/postgres
@desc Updates project's Postgres config
@required {ref: str # Project ref}
@optional {effective_cache_size: str, logical_decoding_work_mem: str, maintenance_work_mem: str, track_activity_query_size: str, max_connections: int, max_locks_per_transaction: int, max_parallel_maintenance_workers: int, max_parallel_workers: int, max_parallel_workers_per_gather: int, max_replication_slots: int, max_slot_wal_keep_size: str, max_standby_archive_delay: str, max_standby_streaming_delay: str, max_wal_size: str, max_wal_senders: int, max_worker_processes: int, session_replication_role: str(origin/replica/local), shared_buffers: str, statement_timeout: str # Default unit: ms, track_commit_timestamp: bool, wal_keep_size: str, wal_sender_timeout: str # Default unit: ms, work_mem: str, checkpoint_timeout: str # Default unit: s, hot_standby_feedback: bool, restart_database: bool}
@returns(200) {effective_cache_size: str, logical_decoding_work_mem: str, maintenance_work_mem: str, track_activity_query_size: str, max_connections: int, max_locks_per_transaction: int, max_parallel_maintenance_workers: int, max_parallel_workers: int, max_parallel_workers_per_gather: int, max_replication_slots: int, max_slot_wal_keep_size: str, max_standby_archive_delay: str, max_standby_streaming_delay: str, max_wal_size: str, max_wal_senders: int, max_worker_processes: int, session_replication_role: str, shared_buffers: str, statement_timeout: str, track_commit_timestamp: bool, wal_keep_size: str, wal_sender_timeout: str, work_mem: str, checkpoint_timeout: str, hot_standby_feedback: bool}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to update project's Postgres config}

@endpoint GET /v1/projects/{ref}/config/realtime
@desc Gets realtime configuration
@required {ref: str # Project ref}
@returns(200) {private_only: bool?, connection_pool: int?, max_concurrent_users: int?, max_events_per_second: int?, max_bytes_per_second: int?, max_channels_per_client: int?, max_joins_per_second: int?, max_presence_events_per_second: int?, max_payload_size_in_kb: int?, suspend: bool?, presence_enabled: bool} # Gets project's realtime configuration
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint PATCH /v1/projects/{ref}/config/realtime
@desc Updates realtime configuration
@required {ref: str # Project ref}
@optional {private_only: bool # Whether to only allow private channels, connection_pool: int # Sets connection pool size for Realtime Authorization, max_concurrent_users: int # Sets maximum number of concurrent users rate limit, max_events_per_second: int # Sets maximum number of events per second rate per channel limit, max_bytes_per_second: int # Sets maximum number of bytes per second rate per channel limit, max_channels_per_client: int # Sets maximum number of channels per client rate limit, max_joins_per_second: int # Sets maximum number of joins per second rate limit, max_presence_events_per_second: int # Sets maximum number of presence events per second rate limit, max_payload_size_in_kb: int # Sets maximum number of payload size in KB rate limit, suspend: bool # Disables the Realtime service for this project when true. Set to false to re-enable it., presence_enabled: bool # Whether to enable presence}
@returns(204)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint POST /v1/projects/{ref}/config/realtime/shutdown
@desc Shutdowns realtime connections for a project
@required {ref: str # Project ref}
@returns(204) Realtime connections shutdown successfully
@errors {401: Unauthorized, 403: Forbidden action, 404: Tenant not found, 429: Rate limit exceeded}

@endpoint POST /v1/projects/{ref}/config/auth/sso/providers
@desc Creates a new SSO provider
@required {ref: str # Project ref, type: str # What type of provider will be created}
@optional {metadata_xml: str, metadata_url: str, domains: [str], attribute_mapping: map{keys!: map}, name_id_format: str(urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified/urn:oasis:names:tc:SAML:2.0:nameid-format:transient/urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress/urn:oasis:names:tc:SAML:2.0:nameid-format:persistent)}
@returns(201) {id: str, saml: map{id: str, entity_id: str, metadata_url: str, metadata_xml: str, attribute_mapping: map{keys: map}, name_id_format: str}, domains: [map], created_at: str, updated_at: str}
@errors {401: Unauthorized, 403: Forbidden action, 404: SAML 2.0 support is not enabled for this project, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/config/auth/sso/providers
@desc Lists all SSO providers
@required {ref: str # Project ref}
@returns(200) {items: [map]}
@errors {401: Unauthorized, 403: Forbidden action, 404: SAML 2.0 support is not enabled for this project, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/config/auth/sso/providers/{provider_id}
@desc Gets a SSO provider by its UUID
@required {ref: str # Project ref, provider_id: str(uuid)}
@returns(200) {id: str, saml: map{id: str, entity_id: str, metadata_url: str, metadata_xml: str, attribute_mapping: map{keys: map}, name_id_format: str}, domains: [map], created_at: str, updated_at: str}
@errors {401: Unauthorized, 403: Forbidden action, 404: Either SAML 2.0 was not enabled for this project, or the provider does not exist, 429: Rate limit exceeded}

@endpoint PUT /v1/projects/{ref}/config/auth/sso/providers/{provider_id}
@desc Updates a SSO provider by its UUID
@required {ref: str # Project ref, provider_id: str(uuid)}
@optional {metadata_xml: str, metadata_url: str, domains: [str], attribute_mapping: map{keys!: map}, name_id_format: str(urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified/urn:oasis:names:tc:SAML:2.0:nameid-format:transient/urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress/urn:oasis:names:tc:SAML:2.0:nameid-format:persistent)}
@returns(200) {id: str, saml: map{id: str, entity_id: str, metadata_url: str, metadata_xml: str, attribute_mapping: map{keys: map}, name_id_format: str}, domains: [map], created_at: str, updated_at: str}
@errors {401: Unauthorized, 403: Forbidden action, 404: Either SAML 2.0 was not enabled for this project, or the provider does not exist, 429: Rate limit exceeded}

@endpoint DELETE /v1/projects/{ref}/config/auth/sso/providers/{provider_id}
@desc Removes a SSO provider by its UUID
@required {ref: str # Project ref, provider_id: str(uuid)}
@returns(200) {id: str, saml: map{id: str, entity_id: str, metadata_url: str, metadata_xml: str, attribute_mapping: map{keys: map}, name_id_format: str}, domains: [map], created_at: str, updated_at: str}
@errors {401: Unauthorized, 403: Forbidden action, 404: Either SAML 2.0 was not enabled for this project, or the provider does not exist, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/database/backups
@desc Lists all backups
@required {ref: str # Project ref}
@returns(200) {region: str, walg_enabled: bool, pitr_enabled: bool, backups: [map], physical_backup_data: map{earliest_physical_backup_date_unix: int, latest_physical_backup_date_unix: int}}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get backups}

@endpoint POST /v1/projects/{ref}/database/backups/restore-pitr
@desc Restores a PITR backup for a database
@required {ref: str # Project ref, recovery_time_target_unix: int(int64)}
@returns(201)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint POST /v1/projects/{ref}/database/backups/restore-point
@desc Initiates a creation of a restore point for a database
@required {ref: str # Project ref, name: str}
@returns(201) {name: str, status: str, completed_on: str(date-time)?}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/projects/{ref}/database/backups/restore-point
@desc Get restore points for project
@required {ref: str # Project ref}
@optional {name: str}
@returns(200) {name: str, status: str, completed_on: str(date-time)?}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded, 500: Failed to get requested restore points}

@endpoint POST /v1/projects/{ref}/database/backups/undo
@desc Initiates an undo to a given restore point
@required {ref: str # Project ref, name: str}
@returns(201)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endgroup

@group organizations
@endpoint GET /v1/organizations/{slug}/members
@desc List members of an organization
@required {slug: str # Organization slug}
@returns(200)

@endpoint GET /v1/organizations/{slug}
@desc Gets information about the organization
@required {slug: str # Organization slug}
@returns(200) {id: str, name: str, plan: str, opt_in_tags: [str], allowed_release_channels: [str]}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/organizations/{slug}/project-claim/{token}
@desc Gets project details for the specified organization and claim token
@required {slug: str # Organization slug, token: str}
@returns(200) {project: map{ref: str, name: str}, preview: map{valid: bool, warnings: [map], errors: [map], info: [map], members_exceeding_free_project_limit: [map], source_subscription_plan: str, target_subscription_plan: str?}, expires_at: str, created_at: str, created_by: str(uuid)}
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint POST /v1/organizations/{slug}/project-claim/{token}
@desc Claims project for the specified organization
@required {slug: str # Organization slug, token: str}
@returns(204)
@errors {401: Unauthorized, 403: Forbidden action, 429: Rate limit exceeded}

@endpoint GET /v1/organizations/{slug}/projects
@desc Gets all projects for the given organization
@required {slug: str # Organization slug}
@optional {offset: int=0 # Number of projects to skip, limit: int=100 # Number of projects to return per page, search: str # Search projects by name, sort: str(name_asc/name_desc/created_asc/created_desc)=name_asc # Sort order for projects, statuses: str # A comma-separated list of project statuses to filter by.  The following values are supported: `ACTIVE_HEALTHY`, `INACTIVE`.}
@returns(200) {projects: [map], pagination: map{count: num, limit: num, offset: num}}
@errors {500: Failed to retrieve projects}

@endgroup

@end
