Functions, Cron & Queues

Functions

Run your code on demand. Each execution runs in an isolated container; your code exports a handler that receives the request and returns a result.

Create & execute
curl -X POST "https://base.finiteskills.com/v1/functions" -H "X-Appwrite-Project: <YOUR_PROJECT_ID>" \
  -H "X-Appwrite-Key: <API_KEY>" -H "Content-Type: application/json" \
  -d '{"functionId":"double","name":"Double","code":"module.exports=({req})=>({n:(req.body.n||0)*2})"}'

curl -X POST "https://base.finiteskills.com/v1/functions/double/executions" \
  -H "X-Appwrite-Project: <YOUR_PROJECT_ID>" -H "X-Appwrite-Key: <API_KEY>" \
  -H "Content-Type: application/json" -d '{"body":{"n":21}}'

The handler signature is ({ req, res, log }) => result. Return a value or call res.json(obj, statusCode). Executions record status, logs, errors and duration. Each function has a configurable timeout (1–300 s) and a memory cap.

Runtimes

Set runtime on create (default node-22). Each execution runs in an isolated container:

Supported runtimes
node-22       // entrypoint index.js
python-3.12   // entrypoint index.py
deno-1        // entrypoint index.js (ESM)

Event triggers

Invoke a function automatically when engine events fire — no polling. Subscribe to one or more event names (or * for all):

Triggers
POST   /functions/{id}/triggers  { "events": ["documentCreated","documentDeleted"] }
GET    /functions/{id}/triggers
DELETE /functions/{id}/triggers/{triggerId}

Event names are the same set the webhook service exposes (documentCreated, documentUpdated, documentDeleted, fileCreated, fileDeleted, sessionCreated, sessionDeleted). The event payload is delivered to the handler.

Variables & secrets

Attach environment variables to a function; they are injected into the runtime. Mark a variable secret to make it write-only — the value is stored encrypted and never returned by GET:

Variables
POST   /functions/{id}/variables  { "key":"STRIPE_KEY", "value":"sk_live_...", "secret":true }
GET    /functions/{id}/variables            # secret values come back as null
DELETE /functions/{id}/variables/{key}

Deployments & rollback

Each deployment is an immutable, versioned snapshot of the code. Creating one makes it the active version; re-activating an older one is an instant rollback:

Versioning
POST /functions/{id}/deployments  { "code":"module.exports=({req})=>({ok:true})" }
  -> { "$id":"dep_...", "version": 4, "status":"active" }
GET  /functions/{id}/deployments                 # history, newest first
POST /functions/{id}/deployments/{depId}/activate  # roll back / roll forward

Cron

POST /cron schedules a recurring job targeting a function or a webhook. Schedules: @every 30s|5m|1h, @hourly, @daily, or a */n * * * * cadence.

Queues

A durable, Postgres-native message queue:

Send / receive / ack
POST /queues/{queue}/messages          { body, delaySeconds }  # enqueue (delaySeconds: hold before first delivery)
POST /queues/{queue}/receive           { max, visibilityTimeout }  # claim
POST /queues/{queue}/messages/{id}/ack                        # delete (done)
POST /queues/{queue}/messages/{id}/nack                       # return to the queue

A received message becomes invisible for its visibility timeout; ack removes it, nack makes it immediately visible again. delaySeconds (up to 900) postpones a message's first delivery.

Dead-letter set

A message that is received more than QUEUE_MAX_RECEIVES times (5 by default) without being acked is treated as poison and moved to the queue's dead-letter set instead of being redelivered forever. Inspect and replay them:

DLQ
GET  /queues/{queue}/dead                        # list dead-lettered messages
POST /queues/{queue}/messages/{id}/requeue       # reset delivery count + make visible again