Triggers
A trigger decides how your function runs. A function can be reached in three ways:
| Trigger | How it fires | Input arrives as |
|---|---|---|
| Manual | You run it on demand (from the dashboard, or however you manage your functions). | ctx.req |
| HTTP | Someone calls a public URL (/api/fn/{slug}). |
ctx.req |
| Event | A change happens in your data (a row is inserted, updated, or deleted). | ctx.event |
You can attach more than one trigger to the same function. Read whichever input applies:
const input = ctx.req ?? ctx.event ?? {};
Manual triggers
Manual runs are the simplest — you invoke the active version yourself and pass an optional payload. The payload becomes ctx.req.
export async function handler(ctx) {
const { name = "world" } = ctx.req ?? {};
return { greeting: `Hello, ${name}!` };
}
Running it with { "name": "Ada" } returns { "greeting": "Hello, Ada!" }.
Manual runs are ideal for testing while you build, for one-off maintenance tasks, and for jobs you kick off by hand.
HTTP triggers
An HTTP trigger gives your function a public URL that your app can call. You pick a slug, and your function becomes reachable at:
POST /api/fn/{slug}
The endpoint accepts GET, POST, PUT, PATCH, and DELETE.
Authentication
HTTP triggers are called by your app users (consumers), using the same Bearer token they use for the rest of the AppAmbit API. The app is derived from that token, so a token can only ever reach its own app's functions.
| Header | Value |
|---|---|
| Authorization | Bearer {CONSUMER_TOKEN} |
| Content-Type | application/json |
See Consumers for how to obtain a consumer token.
What your function receives
For HTTP triggers, ctx.req is the incoming request:
{
"method": "POST",
"slug": "my-endpoint",
"query": { /* query-string parameters */ },
"headers": { /* request headers */ },
"body": { /* parsed JSON body, or form fields */ }
}
The authenticated caller also rides along as ctx.consumer ({ id }) so you know who is calling.
Sensitive headers are stripped
Before your function sees the request, AppAmbit removes the cookie, authorization, and internal auth headers. Don't rely on reading the caller's raw token — use ctx.consumer.id instead.
Shaping the response
By default, whatever you return is sent back as JSON with a 200 status:
export async function handler(ctx) {
return { ok: true }; // → 200, body {"ok":true}
}
To control the status code or headers, return an object with a body (and optional status / headers):
export async function handler(ctx) {
const { id } = ctx.req.body ?? {};
if (!id) {
return { status: 400, body: { error: "id is required" } };
}
return {
status: 201,
headers: { "X-Custom": "yes" },
body: { created: id },
};
}
Status codes you might see
Beyond your own responses, the platform maps certain conditions to HTTP statuses:
| Status | Meaning |
|---|---|
200 |
Success (or your custom status). |
401 |
The caller wasn't authenticated. |
402 |
Your plan doesn't include Cloud Code (when plan enforcement is on). |
404 |
No enabled HTTP trigger matches that slug. |
429 |
You've hit the invocation rate limit — slow down and retry. |
500 |
Your function threw an error or failed. |
503 |
The function has no active version to run. |
504 |
Your function ran past its timeout. |
Every response includes an X-Request-Id header you can use to look up the exact invocation and its logs.
Calling it
You can test an HTTP trigger with any API client (curl, Postman, your app) — it's a normal authenticated AppAmbit API request:
- Get a consumer token for your app — see Consumers.
POST(orGET/PUT/PATCH/DELETE) to/api/fn/{slug}with theAuthorization: Bearerheader. The app is derived from the token, so no app key is needed.- Read the response — your
returnvalue (or thebody/statusyou shaped above), plus anX-Request-Idheader. - Trace the run — pass that
X-Request-Idto the logs to see exactly what your function did on this call.
curl -i -X POST https://api.appambit.com/api/fn/hello \
-H "Authorization: Bearer {CONSUMER_TOKEN}" \
-H "Content-Type: application/json" \
-d '{ "name": "Ada" }'
Testing without deploying
You don't need an HTTP trigger to try a function — use a manual run (see above, or the dashboard "Run" button) to execute the latest version and inspect its output and logs first, then wire up the HTTP trigger once it behaves.
Event triggers
An event trigger runs your function automatically when your data changes — for example, whenever a row is inserted into a table, or an entry is updated in a CMS collection.
An event trigger is configured with:
- a source — your app database (
db) or your CMS (cms), - the table or collection to watch,
- the operations to react to — any of
insert,update,delete.
When it fires, the details of the change arrive as ctx.event:
export async function handler(ctx) {
const change = ctx.event ?? {};
ctx.log("data changed", change);
// react to the change — send a notification, update a summary, etc.
return { handled: true };
}
Great for keeping things in sync
Event triggers shine for reactions you don't want your app to wait on: sending a push when an order row is inserted, recomputing a leaderboard when scores change, or notifying a channel when new content is published.
What's next
-
Configuration & Limits
Set environment variables and secrets, adjust memory and timeout, and understand quotas.
-
Examples & Tips
See HTTP and event functions end to end.