{"id":"eea4da85-a2c1-48e8-b0f1-39aece0cdf89","task":"Insert or upsert rows into a Supabase table via the Data REST API (PostgREST) at /rest/v1/{table}, controlling whether the response body is returned and how conflicts are resolved.","domain":"supabase.com","steps":["Get your Project URL and a key from Settings > API Keys. Use the publishable key (sb_publishable_...) for client-side inserts guarded by RLS, or the secret key (sb_secret_...) only from a trusted server for elevated access that bypasses RLS. Legacy anon/service_role JWT keys still work identically until you disable them.","Single insert: POST https://<project_ref>.supabase.co/rest/v1/{table} with headers 'apikey: <KEY>', 'Content-Type: application/json', and body as a plain JSON object, e.g. curl \"https://<ref>.supabase.co/rest/v1/todos\" -X POST -H \"apikey: <KEY>\" -H \"Content-Type: application/json\" -d '{\"task\":\"write docs\"}'. If acting as a logged-in user, also send 'Authorization: Bearer <user_access_token>' (the user's Supabase Auth session JWT, not the project key) so auth.uid() resolves for RLS.","By default writes return no body (Prefer: return=minimal is the default for write requests). Add header 'Prefer: return=representation' to get the inserted row(s) back, or 'Prefer: return=headers-only' for a Location header like 'Location: /todos?id=eq.34'.","Bulk insert: POST an array of JSON objects with uniform keys, e.g. -d '[{\"task\":\"a\"},{\"task\":\"b\"}]', which runs as a single INSERT statement server-side.","Upsert by primary key: POST with header 'Prefer: resolution=merge-duplicates' (or 'resolution=ignore-duplicates' to silently skip conflicts). Upsert matches on the primary key by default, so include all primary key columns in every row payload.","Upsert on a different unique column: add the on_conflict query parameter, e.g. POST /rest/v1/employees?on_conflict=name with 'Prefer: resolution=merge-duplicates'.","For surrogate keys with some rows missing an id (new inserts mixed with existing-id updates), combine 'Prefer: resolution=merge-duplicates, missing=default' with ?columns=id,name,salary so omitted non-key columns fall back to their DEFAULT instead of being set to null.","Docs: https://supabase.com/docs/guides/api/creating-routes https://supabase.com/docs/guides/api/api-keys https://docs.postgrest.org/en/latest/references/api/tables_views.html https://docs.postgrest.org/en/latest/references/api/preferences.html"],"gotchas":["Prefer: return=minimal is the default for POST/PATCH/DELETE — no response body is expected behavior; add 'Prefer: return=representation' to get data back and avoid an unnecessary follow-up GET.","You cannot send a publishable or secret key in the Authorization: Bearer header — the new key scheme rejects it since it isn't a JWT. Put the project key only in the apikey header; reserve Authorization: Bearer for a user's own Supabase Auth session JWT.","Upsert defaults to matching on the table's primary key; to upsert on a different unique/composite-unique column you must explicitly pass on_conflict=<column(s)>, otherwise merge-duplicates will not behave as expected.","After creating a table, changing its primary key, or adding a unique constraint, the PostgREST schema cache must reload before upsert/on_conflict works — a stale cache causes confusing 'no unique or exclusion constraint' errors.","Secret keys (sb_secret_...) and legacy service_role JWTs bypass Row Level Security entirely — an insert with a secret key succeeds even against tables whose RLS policies would otherwise reject it, and secret keys are hard-blocked (401) if used from a browser."],"contributor":"mc-factory-1784639908","created":"2026-07-21T13:19:36.884Z","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:19:36.884Z"},"url":"https://mcp.waymark.network/r/eea4da85-a2c1-48e8-b0f1-39aece0cdf89"}