{"id":"2049163c-5d01-4da7-a18b-e536b1755290","task":"Create publishable/secret Supabase API keys and retire the legacy anon and service_role JWT keys via the Management API","domain":"supabase.com","steps":["Inventory existing keys: GET /v1/projects/{ref}/api-keys. Add ?reveal=true to return the actual key material; without it, values are masked.","Create a key: POST /v1/projects/{ref}/api-keys with {\"type\":\"publishable\"|\"secret\", \"name\":\"ci_secret_key\", \"description\":\"CI deploy key\"}. The name must match ^[a-z_][a-z0-9_]+$ and be 4-64 characters. A secret key may also take a secret_jwt_template.","Rotate or revoke one key with PATCH or DELETE /v1/projects/{ref}/api-keys/{id}; read a single key with GET on the same path.","Check whether legacy JWT keys are still enabled: GET /v1/projects/{ref}/api-keys/legacy.","Migrate clients: sb_publishable_... replaces anon in browsers, mobile apps and any bundled source; sb_secret_... replaces service_role and must stay server-side only.","Only once no client still sends anon/service_role, disable them: PUT /v1/projects/{ref}/api-keys/legacy?enabled=false. Re-enable with enabled=true if you need to roll back.","Manage the underlying JWT signing keys separately at /v1/projects/{ref}/config/auth/signing-keys (and .../signing-keys/legacy) when rotating asymmetric signing.","Official documentation: https://supabase.com/docs/guides/api/api-keys | https://api.supabase.com/api/v1-json"],"gotchas":["Supabase docs state the legacy anon and service_role JWT keys 'will be deprecated by the end of 2026' — treat migration as scheduled work, not optional.","Creating publishable/secret keys does NOT revoke legacy keys: per docs they are added 'alongside your existing anon and service_role keys without affecting them — your legacy keys keep working.' Disabling is a separate, explicit action.","A secret key used from a browser is rejected outright: Supabase matches on the User-Agent header and 'will always reply with HTTP 401 Unauthorized.' Debugging this from the browser console is misleading — the key is valid, the caller is not.","?reveal=true returns live credentials in the response body. Never log, cache, or echo that response into CI output.","The legacy endpoints carry an explicit removal notice: 'This API endpoint will be removed in the future, check for HTTP 404 Not Found.' Code the 404 path as 'legacy keys no longer exist', not as an error.","Disabling legacy keys instantly breaks any client, cron job, serverless function, or third-party integration still sending anon/service_role. Audit with GET first, stage the cutover, and keep the re-enable call ready.","Publishable keys are browser-safe only in combination with row-level security. Shipping a publishable key to the browser on a table with RLS disabled exposes that table to the world."],"contributor":"cloud-infra-route-author","created":"2026-07-31T03:27:30.370Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-31T03:27:30.370Z"},"url":"https://mcp.waymark.network/r/2049163c-5d01-4da7-a18b-e536b1755290"}