Skip to content
Select themeSelect language

`POST /api/apps/{id}/backend/{function_name}` -- invoke a declared backend function synchronously (ADR 0053). The author-fixed SQL runs under the db_query/db_execute guard with RLS `supacloud.app_id` injected; only the function name + positional args cross the wire, so a caller cannot inject SQL. Authenticated by EITHER a per-deployment App token OR a session.

POST
/api/apps/{id}/backend/{function_name}
curl --request POST \
--url https://example.com/api/apps/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/backend/example \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "args": [ {} ] }'
id
required
string format: uuid

App id

function_name
required
string

Declared backend function name

Media typeapplication/json

POST /api/apps/{id}/backend/{function_name} request body – the positional arguments bound to the function’s $1..$n placeholders. The function name is a path segment, not a body field; the SQL is author-fixed in the manifest.

object
args

Positional arguments, bound in order. Empty for a no-arg function.

Array<object>
object
Examplegenerated
{
"args": [
{}
]
}

Function result (rows / affected count).

Media typeapplication/json

POST /api/apps/{id}/backend/{function_name} response. operation tells the caller how to read the payload: a query returns rows with row_count = rows.len(); an execute returns the affected-row count in row_count and any RETURNING rows in rows.

object
function
required

The invoked function name.

string
operation
required

query or execute.

string
result

script only – the arbitrary JSON value the script returned (a query/ execute returns null here and carries its payload in rows). Omitted from the wire when absent, so the query/execute shape is unchanged. Typed as an UNCONSTRAINED value (a script may return an array/scalar/object) so the generated zod is z.unknown(), not a z.object({}) that would reject a non-object return or strip an object’s keys (the §10 result-shape defect).

row_count
required

Affected-row count (execute) or returned-row count (query).

integer format: int64
rows
required

Query rows, or DML RETURNING rows (empty when the function does not return). Each row is a free-form object — typed as a key-preserving map so the generated zod becomes z.array(z.object({}).catchall(...)) instead of a strict z.array(z.object({})) that zod v4 strips every row column from on parse (the §10 result-table contract defect). Mirrors the proven audit_events.payload_redacted shape.

Array<object>
object
key
additional properties
Examplegenerated
{
"function": "example",
"operation": "example",
"result": "example",
"row_count": 1,
"rows": [
{
"additionalProperty": "example"
}
]
}

Bad args, mis-declared SQL, or no app_db bound.

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}

Missing/invalid App token or session.

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}

App token does not authorize this app.

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}

App or function not found.

Media typeapplication/json

The canonical JSON body of every error response — the single source of truth the frontend binds to. Every AppError serializes as this exact shape, and the generated OpenAPI component ApiErrorBody (with its ErrorCode enum) is what the frontend error schema is generated from, so there is no hand-written error schema on either end.

object
code
required

Machine-readable, stable error code.

string
Allowed values: not_found unauthorized forbidden bad_request unprocessable precondition_failed conflict method_not_allowed rate_limited quota_exceeded database_error docker_error vault_error internal_error
details
One of:
null
error
required

Human-readable message (the server’s English text; the client may localize by code).

string
Example
{
"code": "not_found"
}