Read and write rows
Select, insert, update, upsert and delete rows.
/supabase/{database_id}/rest/v1/{table}
Reads and writes the same rows as the other entry point for this database. Errors use PostgREST codes.
Support matrix and client setup
Parameters and request headers
| Name | Location | Description |
|---|---|---|
| database_id | path | Database ID. |
| table | path | table ID or name. |
| select | query | Comma-separated columns; supports *, aliases, JSON paths and link-based embedding. Casts, aggregates, spread and join modifiers are unsupported. |
| {column} | query | Horizontal filter: replace {column} with a field name or JSON path, e.g. title=eq.summary. Repeat for more columns. See the filter operator matrix. |
| and | query | Parenthesized conditions, e.g. (done.eq.false,title.neq.draft). |
| or | query | Parenthesized alternatives; not.and and not.or are also supported. |
| not.and | query | Negated conjunction. |
| not.or | query | Negated disjunction. |
| order | query | Comma-separated columns with asc/desc and nullsfirst/nullslast; JSON paths allowed. |
| limit | query | Maximum returned rows. |
| offset | query | Rows to skip. |
| on_conflict | query | POST upsert: id or one unique field; use Prefer: resolution=merge-duplicates or ignore-duplicates. |
| columns | query | Comma-separated input columns; keys outside this set are ignored. |
| Range | header | GET/HEAD inclusive row interval, e.g. 0-9. Intersects limit/offset. |
| Range-Unit | header | items; other units cause Range to be ignored. |
| Prefer | header | Comma-separated preferences. Unknown preferences are ignored unless handling=strict (400 PGRST122). |
| Accept | header | application/json, /, or application/vnd.pgrst.object+json. Singular output requires exactly one row; otherwise 406 PGRST116. Other media types return 406 PGRST107; text/csv, application/geo+json and application/vnd.pgrst.plan return 400 PGRST127. |
| If-None-Match | header | Entity tag from a previous GET or HEAD (weak comparison). When it matches the current ETag the response is 304 with no body. |
POST accepts an object or an array of objects; PATCH accepts an object. System columns are managed by the service. Writes return no body by default; Prefer: return=representation (SDK .select()) returns rows. PATCH and DELETE affect rows matching the filters; omitting filters matches all rows.
| Response header | Meaning |
|---|---|
| Content-Range | Returned range/total; total is * when no count is requested. |
| Preference-Applied | Applied preferences. |
| ETag | Entity tag returned by GET/HEAD; a matching If-None-Match returns 304 with no body. |
| Location | New row URL for POST with return=headers-only. |
Reads normally return 200, or 206 when count is requested and only some rows are returned. A matching If-None-Match returns 304. datetime values are stored and read back in UTC with exactly three fractional digits (e.g. 2026-10-11T00:30:00.000Z); precision is milliseconds and extra fractional digits are rounded half up. POST returns 201. PATCH/DELETE return 200 with representation, otherwise 204. HEAD has no body.
Select rows
GET /supabase/{database_id}/rest/v1/{table}
const { data, error } = await supabase.from("tasks").select("*").order("title").limit(10);
if (error) throw error;
console.log(data);Response
HTTP 200
Success; write bodies require Prefer: return=representation
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | |
| [].version | integer | |
| [].created_at | string | |
| [].updated_at | string |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | |
| version | integer | |
| created_at | string | |
| updated_at | string |
HTTP 206
Partial range with requested count
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | |
| [].version | integer | |
| [].created_at | string | |
| [].updated_at | string |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | |
| version | integer | |
| created_at | string | |
| updated_at | string |
Response example — HTTP 200
| Header | Value |
|---|---|
| content-range | 0-0/* |
| etag | W/"5.1" |
| range-unit | items |
[
{
"id": "rec_e88fcbd357aa49c9",
"version": 1,
"created_at": "2026-10-11T17:42:00.094Z",
"updated_at": "2026-10-11T17:42:00.094Z",
"title": "Write a summary",
"done": false
}
]Count rows
HEAD /supabase/{database_id}/rest/v1/{table}
const { data, error, count } = await supabase.from("tasks").select("*", { head: true, count: "exact" });
if (error) throw error;
console.log(count);Response
HTTP 200
Success; write bodies require Prefer: return=representation
No response body is declared.
HTTP 206
Partial range with requested count
No response body is declared.
Response example — HTTP 200
| Header | Value |
|---|---|
| content-range | 0-0/1 |
| preference-applied | count=exact |
| etag | W/"5.1" |
| range-unit | items |
No response body.
Insert rows
POST /supabase/{database_id}/rest/v1/{table}
const { data, error } = await supabase.from("tasks").insert({"title":"Write a summary","done":false}).select();
if (error) throw error;
console.log(data);Response
HTTP 201
Success; write bodies require Prefer: return=representation
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | |
| [].version | integer | |
| [].created_at | string | |
| [].updated_at | string |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | |
| version | integer | |
| created_at | string | |
| updated_at | string |
Response example — HTTP 201
| Header | Value |
|---|---|
| content-range | 0-0/* |
| preference-applied | return=representation |
| range-unit | items |
[
{
"id": "rec_e88fcbd357aa49c9",
"version": 1,
"created_at": "2026-10-11T17:42:00.094Z",
"updated_at": "2026-10-11T17:42:00.094Z",
"title": "Write a summary",
"done": false
}
]Update rows
PATCH /supabase/{database_id}/rest/v1/{table}
const { data, error } = await supabase.from("tasks").update({ done: true }).eq("title", "Write a summary").select();
if (error) throw error;
console.log(data);Response
HTTP 200
Success; write bodies require Prefer: return=representation
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | |
| [].version | integer | |
| [].created_at | string | |
| [].updated_at | string |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | |
| version | integer | |
| created_at | string | |
| updated_at | string |
HTTP 204
Success without a body
No response body is declared.
Response example — HTTP 200
| Header | Value |
|---|---|
| content-range | 0-0/* |
| preference-applied | return=representation |
| range-unit | items |
[
{
"id": "rec_e88fcbd357aa49c9",
"version": 2,
"created_at": "2026-10-11T17:42:00.094Z",
"updated_at": "2026-10-11T17:42:01.047Z",
"title": "Write a summary",
"done": true
}
]Upsert rows
POST /supabase/{database_id}/rest/v1/{table}
const { data, error } = await supabase.from("tasks").upsert({"title":"Write a summary","done":true}, { onConflict: "title" }).select();
if (error) throw error;
console.log(data);Response
HTTP 201
Success; write bodies require Prefer: return=representation
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | |
| [].version | integer | |
| [].created_at | string | |
| [].updated_at | string |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | |
| version | integer | |
| created_at | string | |
| updated_at | string |
Response example — HTTP 201
| Header | Value |
|---|---|
| content-range | 0-0/* |
| preference-applied | resolution=merge-duplicates, return=representation |
| range-unit | items |
[
{
"id": "rec_e88fcbd357aa49c9",
"version": 3,
"created_at": "2026-10-11T17:42:00.094Z",
"updated_at": "2026-10-11T17:42:01.735Z",
"title": "Write a summary",
"done": true
}
]Delete rows
DELETE /supabase/{database_id}/rest/v1/{table}
const { data, error } = await supabase.from("tasks").delete().eq("title", "Write a summary").select();
if (error) throw error;
console.log(data);Response
HTTP 200
Success; write bodies require Prefer: return=representation
application/json
| Name | Type | Description |
|---|---|---|
| [].id | string | |
| [].version | integer | |
| [].created_at | string | |
| [].updated_at | string |
application/vnd.pgrst.object+json
| Name | Type | Description |
|---|---|---|
| id | string | |
| version | integer | |
| created_at | string | |
| updated_at | string |
HTTP 204
Success without a body
No response body is declared.
Response example — HTTP 200
| Header | Value |
|---|---|
| content-range | 0-0/* |
| preference-applied | return=representation |
| range-unit | items |
[
{
"id": "rec_e88fcbd357aa49c9",
"version": 3,
"created_at": "2026-10-11T17:42:00.094Z",
"updated_at": "2026-10-11T17:42:01.735Z",
"title": "Write a summary",
"done": true
}
]