Insert data
Insert one row (Hash) or many (Array<Hash>) into a table.
Insert one or many rows into a table. The first argument can be a single Hash (single-row insert) or an Array<Hash> (bulk insert — PostgREST infers the column list from the first row's keys).
Signature
supabase.from(table).insert(json, count: nil, returning: "representation", upsert: false, default_to_null: true)Parameters
| Name | Type | Required | Description |
|---|---|---|---|
json | Hash or Array<Hash> | Required | Row payload. A Hash inserts one row; an Array<Hash> bulk-inserts. For bulk inserts PostgREST takes the column list from the union of the rows hash keys. |
count | String | Optional | One of "exact", "planned", "estimated". Adds Prefer: count=... so APIResponse#count is populated from the Content-Range header. |
returning | String | Optional | "representation" (default) returns the inserted rows; "minimal" returns no body, which is faster for fire-and-forget writes. |
upsert | Boolean | Optional | When true, adds Prefer: resolution=merge-duplicates so a primary-key/unique conflict overwrites the existing row instead of failing. Prefer the dedicated upsert builder if you need the full upsert vocabulary (on_conflict, ignore_duplicates). |
default_to_null | Boolean | Optional | When false, adds Prefer: missing=default so columns missing from the payload fall back to their column DEFAULT instead of NULL. Useful for bulk inserts where rows have differing key sets. |
Returns
A chainable builder. Call .execute to fire the request and receive an APIResponse (data: lists the inserted rows when returning: "representation").
Example — insert a single row
response = supabase
.from("countries")
.insert(name: "Wakanda", continent: "Africa")
.execute
response.data # => [{ "id" => 250, "name" => "Wakanda", "continent" => "Africa" }]Example — bulk insert
Pass an Array<Hash> to insert many rows in one request. PostgREST collects the column list from the union of every row's keys; rows missing a key receive NULL (or the column default — see default_to_null:).
response = supabase
.from("countries")
.insert([
{ name: "Wakanda", continent: "Africa" },
{ name: "Genosha", continent: "Africa" },
{ name: "Latveria", continent: "Europe" }
])
.execute
response.data.length # => 3Example — fire-and-forget (no body back)
returning: "minimal" returns no body, so data is []. Use this when you don't need the inserted row(s) and want to skip the serialization cost.
supabase
.from("audit_log")
.insert({ event: "login", user_id: 42 }, returning: "minimal")
.execute
# response.data => []Example — count without representation
response = supabase
.from("countries")
.insert([{ name: "Wakanda" }, { name: "Genosha" }], count: "exact")
.execute
response.count # => 2Example — insert + chained select
select after insert flips the Prefer header to return=representation (overriding returning:) and adds a select= query parameter so you can shape the response.
response = supabase
.from("countries")
.insert(name: "Wakanda")
.select("id, name")
.execute
response.data # => [{ "id" => 250, "name" => "Wakanda" }]Types::ReturnMethod::REPRESENTATION / ::MINIMAL are the constants behind the string values for returning:.