Backend function reference
What a backend function receives and can reach: the event, ctx.secrets, ctx.fetch, ctx.entity, ctx.email, ctx.ai and ctx.log, return shapes, visibility and running as the app.
Last updated September 17, 2026
On this page
A backend function is the body of an async JavaScript function. event and ctx are already in scope; whatever you return goes back to the caller.
event
| Field | Meaning |
|---|---|
event.<anything> | What the caller sent: the payload from fn.invoke, the API body, or the webhook delivery |
event.user | The signed-in user who called it, when there is one |
event.ip | The caller's address |
event.request | For webhooks: raw_body (the exact bytes the sender signed) and headers (lower-cased) |
event.api_key | The API key used, when called over the API |
ctx
| Member | Does |
|---|---|
ctx.secrets.get(NAME) | A stored secret the function declared |
await ctx.fetch(url, init) | An outbound request to a host the function declared |
ctx.entity("Name") | The app's tables, with the caller's permissions (or the app's, when running as the app) |
await ctx.email.send({ to, subject, body }) | Send email from the app |
await ctx.ai.invoke({ prompt, ... }) | Call AI, same options as the page SDK |
ctx.log(...) | A line in the run's log |
Return shapes from ctx.entity
| Call | Resolves to |
|---|---|
.list(options) | { ok, total, records } |
.filter(conditions) | An array of rows |
.get(id) | { ok, record } |
.create(data) | { ok, id, record } |
.update(id, data) | { ok, record } |
.archive(id) | { ok } |
Settings on a function
| Setting | Values |
|---|---|
| Visibility | public, users (default), admin, internal |
| Egress hosts | The outside hostnames it may call. Enforced |
| Secret names | The stored secrets it may read. Enforced |
| Runs as | the caller (default) or the app. Running as the app reads and writes every table regardless of who called |
| Enabled | A new function starts off; the builder switches it on once tested |
A complete example
JavaScript
// stripe_payments: a webhook handler. Visibility public, secret STRIPE_WEBHOOK_SECRET declared.
const secret = ctx.secrets.get("STRIPE_WEBHOOK_SECRET");
const sig = event.request.headers["stripe-signature"];
if (!verifyStripeSignature(event.request.raw_body, sig, secret)) {
return { ok: false, error: "bad_signature" };
}
const evt = JSON.parse(event.request.raw_body);
const seen = await ctx.entity("StripeEvent").filter({ stripe_id: evt.id });
if (seen.length) return { ok: true, duplicate: true };
await ctx.entity("StripeEvent").create({ stripe_id: evt.id, type: evt.type });
if (evt.type === "payment_intent.succeeded") {
const orderId = evt.data.object.metadata.order_id;
await ctx.entity("Order").update(orderId, { status: "paid" });
ctx.log("order paid", orderId);
}
return { ok: true };Calling one
- From a page:
await fn.invoke("name", payload). - From your server:
POST /api/functions/<name>with a secret key. See Calling backend functions. - From a schedule or a data change: an automation.
- From another company's server: a webhook at
/api/webhooks/<name>.
Was this page helpful?