Setu Recipes: reusable digital workers across every app.Browse templates

Integrations / PostgreSQL (PostgREST)

PostgreSQL (PostgREST)

Read and change PostgreSQL tables over HTTP through PostgREST, the standard REST layer for Postgres that you run yourself (or get hosted, as with Supabase at /rest/v1): select with filters, insert, upsert, update, delete and call functions. Direct SQL connections are not offered, because Postgres speaks its own wire protocol, not HTTP; to run SQL use the Neon or Supabase toolkits.

8 actions API key 3 read4 write1 destructive Calls postgrest.org

Connect

TypeScript
const conn = await setu.connections.initiate({ userId: "user_1", toolkit: "postgresql" });
console.log(conn.connectUrl); // show this to your user
await conn.waitUntilActive();

Permissions requested

This toolkit uses a single credential and requests no scopes.

Actions

Call a functionwritepostgresql.call_functionCall a PostgreSQL function through PostgREST with POST /rpc/<name> and a JSON object of named arguments. The function may change data, so it is a write; for functions that only read, call_read_function is the safer choice.
InputTypeDescription
pathstringRequiredFunction path: /rpc/<function_name> (with Supabase /rest/v1/rpc/<function_name>)
bodyobjectOptionalThe function's arguments by name, e.g. {"a":1,"b":2}
TypeScript
await setu.execute({
  userId: "user_1",
  action: "postgresql.call_function",
  input: {
    "path": "<path>"
  },
});
Call a read-only functionreadpostgresql.call_read_functionCall a PostgreSQL function that does not modify data through PostgREST with GET /rpc/<name>?arg=value. Pass the function's arguments by name in query. Scalar functions return the bare value and table functions return a list of rows.
InputTypeDescription
pathstringRequiredFunction path: /rpc/<function_name> (with Supabase /rest/v1/rpc/<function_name>)
queryobjectOptionalPostgREST URL parameters as name to text/number pairs. The function's arguments by name, e.g. {"a":1,"b":2}
TypeScript
await setu.execute({
  userId: "user_1",
  action: "postgresql.call_read_function",
  input: {
    "path": "<path>"
  },
});
Delete rowsdestructivepostgresql.delete_rowsDelete the rows matching filters and return the deleted rows. At least one filter is required here, because PostgREST would otherwise delete every row in the table. Example: query {"id":"eq.1"}.
InputTypeDescription
pathstringRequiredTable path: starts with /, e.g. /people. Use the table or view name; with Supabase add the /rest/v1 prefix
queryobjectRequiredFilters choosing the rows to delete, e.g. {"id":"eq.1"} (required, not empty)
TypeScript
await setu.execute({
  userId: "user_1",
  action: "postgresql.delete_rows",
  input: {
    "path": "<path>",
    "query": {}
  },
  confirm: true,
});
Describe the APIreadpostgresql.get_schemaFetch the OpenAPI description PostgREST serves on its root path: the API title and the tables, views and their columns visible to the token's role. Use it to discover table and column names before select_rows.
InputTypeDescription
pathstringRequiredRoot path of the API: / for PostgREST, /rest/v1/ for Supabase
TypeScript
await setu.execute({
  userId: "user_1",
  action: "postgresql.get_schema",
  input: {
    "path": "<path>"
  },
});
Insert rowswritepostgresql.insert_rowsInsert one row (JSON object) or several rows (JSON array of objects with the same keys) into a table and return the inserted rows. Fails on a unique-key conflict; use upsert_rows to update instead.
InputTypeDescription
pathstringRequiredTable path: starts with /, e.g. /people. Use the table or view name; with Supabase add the /rest/v1 prefix
bodyobject,arrayRequiredOne row as an object, or a list of rows as an array of objects with matching keys
TypeScript
await setu.execute({
  userId: "user_1",
  action: "postgresql.insert_rows",
  input: {
    "path": "<path>",
    "body": "<body>"
  },
});
Select rowsreadpostgresql.select_rowsRead rows from a table or view. Choose columns with select, filter with column=operator.value (eq, neq, gt, gte, lt, lte, like, ilike, in, is, fts; for example age=lt.13, status=in.(open,new), or=(age.lt.18,age.gt.21)), sort with order (age.desc) and page with limit and offset or the range input. Conditions on different columns are ANDed.
InputTypeDescription
pathstringRequiredTable or view path: starts with /, e.g. /people. Use the table or view name; with Supabase add the /rest/v1 prefix
queryobjectOptionalPostgREST URL parameters as name to text/number pairs. Examples: {"select":"first_name,age","age":"lt.13","order":"age.desc","limit":25,"offset":50}
rangestringOptionalOptional row range instead of limit/offset, as first-last (0-24 is the first 25 rows)
TypeScript
await setu.execute({
  userId: "user_1",
  action: "postgresql.select_rows",
  input: {
    "path": "<path>"
  },
});
Update rowswritepostgresql.update_rowsUpdate the rows matching filters and return them. At least one filter is required here, because PostgREST would otherwise update every row in the table. Example: query {"id":"eq.1"} with body {"age":13}.
InputTypeDescription
pathstringRequiredTable path: starts with /, e.g. /people. Use the table or view name; with Supabase add the /rest/v1 prefix
queryobjectRequiredFilters choosing the rows to update, e.g. {"id":"eq.1"} or {"age":"lt.13"} (required, not empty)
bodyobjectRequiredColumns to change, as column to new value pairs
TypeScript
await setu.execute({
  userId: "user_1",
  action: "postgresql.update_rows",
  input: {
    "path": "<path>",
    "query": {},
    "body": {}
  },
});
Upsert rowswritepostgresql.upsert_rowsInsert rows, or update the existing row when a unique key already matches (merge duplicates), and return the resulting rows. By default the primary key decides; name another UNIQUE column with query {"on_conflict":"email"}. Send all primary key columns in each row.
InputTypeDescription
pathstringRequiredTable path: starts with /, e.g. /people. Use the table or view name; with Supabase add the /rest/v1 prefix
queryobjectOptionalPostgREST URL parameters as name to text/number pairs. Usually {"on_conflict":"<unique column>"}; omit to use the primary key
bodyobject,arrayRequiredOne row as an object, or a list of rows as an array of objects with matching keys
TypeScript
await setu.execute({
  userId: "user_1",
  action: "postgresql.upsert_rows",
  input: {
    "path": "<path>",
    "body": "<body>"
  },
});