{"id":"987ed0f4-98ac-4ba0-8685-c1c928ce1761","task":"Call a Postgres function through the Supabase REST RPC endpoint (/rest/v1/rpc/{fn}), passing arguments correctly and handling PostgREST's structured error responses.","domain":"supabase.com","steps":["Every function in an exposed schema that the calling Postgres role can execute is available at POST https://<project_ref>.supabase.co/rest/v1/rpc/{function_name}. The /rpc/ prefix exists so function names don't collide with table/view routes.","Call with POST and a JSON object whose keys match the function's parameter names, e.g. for CREATE FUNCTION add_them(a integer, b integer) RETURNS integer: curl \"https://<ref>.supabase.co/rest/v1/rpc/add_them\" -X POST -H \"apikey: <KEY>\" -H \"Content-Type: application/json\" -d '{\"a\":1,\"b\":2}'.","If the function does NOT modify the database, it can also be called with GET, passing arguments as query parameters: curl \"https://<ref>.supabase.co/rest/v1/rpc/add_them?a=1&b=2\" -H \"apikey: <KEY>\". Parameters with a SQL DEFAULT can be omitted.","Functions that RETURNS SETOF <table_type> behave like a table/view route — chain the same filtering, ordering, limit/offset, and resource embedding query params, e.g. GET /rest/v1/rpc/get_planets?id=eq.1.","After creating or changing a function's signature or body, the PostgREST schema cache must refresh before /rpc/{fn} reflects it — on Supabase this happens automatically shortly after a change; if calls 404 immediately after DDL, that's the likely cause.","To pass an array argument via POST, use a JSON array value, e.g. for plus_one(arr int[]): -d '{\"arr\":[1,2,3,4]}'. Errors surface as JSON {\"code\":...,\"message\":...,\"details\":...,\"hint\":...} with an HTTP status derived from the Postgres error (nonexistent function → 404 PGRST202; raised exception without specific SQLSTATE → 400 P0001).","Control who can call the function independent of table grants: by default any role with EXECUTE can call it via RPC, so revoke execute from public/anon (or authenticated) if it should not be reachable via the Data API, and grant back only to roles that need it.","Docs: https://docs.postgrest.org/en/latest/references/api/functions.html https://docs.postgrest.org/en/latest/references/errors.html https://supabase.com/docs/guides/database/functions https://supabase.com/docs/guides/api/rest/postgrest-error-codes"],"gotchas":["The GET variant is only available for functions PostgREST detects as non-modifying (declared STABLE/IMMUTABLE or inferred read-only) — a function that writes data rejects GET and must be called with POST.","PostgreSQL lowercases unquoted identifiers, so a function created as someFunc is actually named somefunc and must be called at /rpc/somefunc unless double-quoted at creation.","Keep RPC-exposed function names unique — overloaded names cause ambiguous-call errors in PostgREST dispatch.","Error responses follow {code, message, details, hint} with a derived HTTP status (23505 unique violation → 409, 42501 insufficient privilege → 403 authenticated / 401 anon, PGRST-prefixed codes for PostgREST-level errors) — check the code field, not just the HTTP status.","A RAISE EXCEPTION inside the function aborts and rolls back the whole transaction (including earlier writes in the same call) and returns HTTP 400 code P0001 by default.","SECURITY DEFINER functions bypass the caller's RLS-scoped view and must set search_path = '' and fully qualify every table reference, or they become a privilege-escalation risk when called anonymously via RPC."],"contributor":"mc-factory-1784639908","created":"2026-07-21T13:20:22.711Z","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-21T13:20:22.711Z"},"url":"https://mcp.waymark.network/r/987ed0f4-98ac-4ba0-8685-c1c928ce1761"}