Reference
Supabase Project APIs
Query a Supabase project through Alter Vault without exposing its API key
Overview
Section titled “Overview”Use a Supabase project API key to call the project’s Data, Auth, Storage, Edge Functions, Realtime, and GraphQL APIs through Alter Vault. Alter’s backend sends the key in Supabase’s required apikey header; application and SDK processes do not receive it on the proxy path.
| Property | Value |
|---|---|
| Provider ID | supabase |
| Category | Developer Tools |
| Credential Type | API Key Header (apikey) |
Step 1: Get Credentials
Section titled “Step 1: Get Credentials”Log in and select your project
Open the Supabase Dashboard and select the project Alter should access.
Open API Keys
Go to Settings → API Keys.
Copy a project API key
Copy an sb_publishable_... or sb_secret_... key. Hosted keys use Supabase’s 22-character random value + underscore + 8-character checksum format. Supabase also accepts legacy anon and service_role JWT keys in the apikey header.
Copy the Project URL
Copy the Project URL, such as https://your-project.supabase.co, or the HTTPS custom domain configured for that project. Alter also accepts the bare hostname.
Step 2: Add to Alter Vault
Section titled “Step 2: Add to Alter Vault”Choose Managed Secrets → Add Managed Secret → Supabase Project APIs, then enter the project API key and Project URL. Alter binds the credential to that exact project hostname and validates it through the project’s API-key gateway using the public Auth settings endpoint. This works for publishable/anon as well as secret/service-role keys; Supabase’s /rest/v1/ OpenAPI root no longer accepts public keys even though ordinary table routes do. A definitive Supabase rejection fails the save; an inconclusive response is reported without misclassifying a valid restricted key. The generic allowed-hosts editor cannot widen or clear this binding.
To move the secret to another project, rotate it with the new API key and project_url. Leaving Project URL blank during rotation preserves the current binding.
Every rotation reapplies the built-in Supabase Project APIs contract (apikey plus the exact project host); stored injection metadata is not treated as operator-editable configuration. If Alter cannot read the existing project binding, rotation fails before writing a new credential and asks for project_url explicitly.
Older Alter installations stored both Supabase surfaces under supabase. A historical row is visibly marked for repair until Alter can classify its Vault credential without changing its destination. If the row already has the matching project host, first use repairs it atomically. Otherwise, edit the secret and rotate with a project key plus Project URL. To deliberately convert an eligible historical row to account-level Management access, rotate with an sbp_ personal access token and complete the explicit type-to-confirm step; Alter removes the project binding and repoints every existing grant to api.supabase.com. Current Project API secrets cannot be converted in place.
Using in Code
Section titled “Using in Code”response = await alter_app.request( HttpMethod.GET, "https://your-project.supabase.co/rest/v1/your_table?select=*", grant_id="YOUR_GRANT_ID",)The SDK sends the unsigned request metadata to Alter. After policy, exact-host, and normalized project-path checks pass, Alter’s backend injects apikey: YOUR_PROJECT_KEY and executes the provider request. The allowed project surfaces are /rest/v1, /auth/v1, /storage/v1, /functions/v1, /realtime/v1, and /graphql/v1; every other path and every other host is rejected before credential injection. Do not put the project key or an Authorization header in application request headers.
Policy-cataloged operations
Section titled “Policy-cataloged operations”| Operation ID | Families | Method | Provider path |
|---|---|---|---|
describe_data_api | read | GET | /rest/v1 |
read_table_rows | admin, delete, payment, read, send, write | GET | /rest/v1/{table} |
inspect_table_rows | admin, delete, payment, read, send, write | HEAD | /rest/v1/{table} |
create_table_rows | admin, delete, payment, read, send, write | POST | /rest/v1/{table} |
replace_table_rows | admin, delete, payment, read, send, write | PUT | /rest/v1/{table} |
update_table_rows | admin, delete, payment, read, send, write | PATCH | /rest/v1/{table} |
delete_table_rows | admin, delete, payment, read, send, write | DELETE | /rest/v1/{table} |
read_database_function | admin, delete, payment, read, send, write | GET | /rest/v1/rpc/{function} |
call_database_function | admin, delete, payment, read, send, write | POST | /rest/v1/rpc/{function} |
project_auth_* | admin, delete, payment, read, send, write | supported HTTP methods | /auth/v1[/…] |
project_storage_* | admin, delete, payment, read, send, write | supported HTTP methods | /storage/v1[/…] |
project_functions_* | admin, delete, payment, read, send, write | supported HTTP methods | /functions/v1[/…] |
project_realtime_* | admin, delete, payment, read, send, write | supported HTTP methods | /realtime/v1[/…] |
project_graphql_* | admin, delete, payment, read, send, write | supported HTTP methods | /graphql/v1[/…] |
Project-defined tables, views, functions, triggers, webhooks, Auth hooks, Storage policies, and GraphQL resolvers can have arbitrary side effects. Until a project-specific attestation exists, every project-defined operation deliberately carries the complete policy-family union. This conservative posture means a family deny for send, payment, or admin cannot be bypassed by hiding that action behind an apparently ordinary read or write.