Script

Script is a declarative backend endpoint that a frontend calls over HTTP. Rather than writing server code, you declare "what to do" as JSON and the WEEGLOO engine runs it for you. The goal is to replace, with a single Script, the typical backend plumbing that supports a frontend (a BFF, Backend-for-Frontend): authentication, guards, chained CRUD, external API calls, and value shaping.

This document set is the reference for Script syntax. The details of each part of the syntax are split across the pages in Documents in this group below.

Creating and managing a Script (create, read, update, delete) happens on CMA (https://cma.weegloo.com/v1). Execution is handled by the execution path on the dedicated Script host (https://script.weegloo.com/v1). That one execution path accepts both a Weegloo User token and the token of a member who has signed up for the product (a ServiceUser). ACMA has no Script API, and neither do the read-only delivery APIs (CDA, ACDA).

Mental model

  • One Script is one HTTP endpoint. The call method (method) determines which Script runs.
  • The body is a statements array. They run sequentially, top to bottom. This is the same as the body of a function in ordinary programming.
  • It is declaration, not code. You do not embed arbitrary code (FaaS); you compose predefined statement types. It is designed less for hand-authoring by a person and more for generation by an AI agent over MCP.
  • Values flow through JSON Pointer templates. You reference the result of a previous step, the input payload, or a variable with { /pointer } and pass it to the next step. When you need a condition or a calculation, you use JsonLogic operators. The full rules are covered in Value Expressions.

Top-level structure (ScriptDefinition)

A single Script is defined by the following ScriptDefinition structure.

{
  "method": "Post",               // Get | Post | Put | Patch | Delete. The HTTP method matched on call (required)
  "payloadSchema": { /* ... */ }, // (optional) JSON Schema. If present, validates the request payload before execution
  "statements": [ /* Statement[]. Executed from top to bottom (required, at least 1) */ ]
}
FieldRequiredDescription
methodRequiredThe HTTP method used to call this Script. Calls are matched by this value.
payloadSchemaOptionalA JSON Schema. If specified, the request body (payload) is validated against this schema before execution, and if validation fails the request is rejected without being executed.
statementsRequiredAn ordered array of statements to run. At least one.

The payload accepts a JSON object only. The call body is accessed through the /payload context root ({ /payload/... }), and when you need the raw body string before parsing you access it through /rawPayload (for cases such as signature verification, where the computation runs over the bytes as sent). The call's request HTTP headers are referenced through the /headers root ({ /headers/... }, with lowercase keys). The time at which execution started is in the /now root. The full set of context roots is covered in Value Expressions.

Request and response

In the end, a Script returns the value of its Return statement to the caller. The response has the following shape.

{
  "requestId": "…",     // Execution identifier
  "durationMs": 1234,   // Execution time (ms)
  "statusCode": 200,    // The statusCode of the Return that was reached (default 200)
  "return": <value>     // Only when Return.isError is false. If the value is null, ""
  // "error": <value>   // When Return.isError is true, or when the execution failed (in which case "return" is absent). If the value is null, ""
}
  • requestId is the identifier of this execution. The same value goes into sys.requestId on the ScriptLog that the execution leaves behind, so it is the key to finding this execution in the logs.
  • return and error never appear together. The isError of the Return statement decides which one it is.
  • If the Script ends without reaching a Return statement, return and error are both absent and statusCode is the default (200).
  • If the execution fails, error is filled in even without a Return. When the failure comes from the caller's side, such as an invalid payload, and no Try catches it, error carries the reason for the failure and statusCode becomes the code that corresponds to that failure (4xx for an invalid payload, 502 when an external call or a mail send fails). In practice this is the error response you meet most often. An execution that goes past its time budget answers with 408 instead of the envelope.
  • If a value is null, that field is emitted as an empty string "".

You control the response body and the status code with the Return statement's value, isError, and statusCode. For details, see Return in the Statement Catalog.

How much time one execution gets

A Script runs inline, on the path that handles the call request. There is no flow that hands the work to the background or returns an acknowledgement first, and the response body of the call is the execution result. There is no polling path for collecting the result later either.

The time one execution gets is decided by a single expression: min(30s + the sum of the times the statements declare, 180s).

  • The base budget is 30 seconds. The time each statement declares is added on top of that.
  • A statement that declares nothing counts as 0 seconds. The time such a statement actually spends comes out of the 30-second base budget.
  • If the sum goes past 180 seconds, the save is not rejected. Instead, the budget is cut off at 180 seconds.

Here is the gist of the declaration rule for each statement.

StatementTime it declares
Http(timeoutMs, or 30s if absent) × (1 + retry)
EmailSendtimeoutMs, or 10s if absent
LoopThe sum of the body statements × (maxIterations, or 10,000 if absent)
ResourceForEachThe sum of the onEach statements × (limit, or 10,000 if absent)
IfThe larger of the then side and the else side
ParallelThe largest of the branches
  • Iteration multiplies. Loop and ResourceForEach multiply the time the body (onEach) declares by the iteration ceiling.
  • An iteration with no external calls has a body that declares 0, so the 30-second base budget is the real limit.

The detailed per-statement rules and the plan limits are covered in Execution Semantics, Constraints, and Security.

Minimal example

It creates a post Content from the title and body in the request payload, publishes it right away, and then returns the sys.id it created.

{
  "method": "Post",
  "statements": [
    { "type": "ResourceCreate", "resource": "Content",
      "contentType": { "sys": { "id": "ct_post" } },
      "fields": {
        "title": { "en-US": "{ /payload/fields/title }" },
        "body":  { "en-US": "{ /payload/fields/body }" }
      },
      "publish": true,
      "name": "post" },
 
    { "type": "Return", "value": { "id": "{ /post/sys/id }" }, "statusCode": 201 }
  ]
}
  • ResourceCreate creates the Content and binds the result to the name post.
  • Return returns { "id": <new Content id> } with 201.
  • Why a Content's fields values are locale maps ({ "en-US": ... }) is covered in Locale maps in Value Expressions.

You'll find more varied scenarios in the Cookbook.

Documents in this group

  • Value Expressions: Covers { /pointer } references, literals, JsonLogic operations and conditions, context roots, and locale maps. This is the heart of the syntax.
  • Statement Catalog: Covers the fields and results of the 25 statement types (resource CRUD and reads, Http, EmailSend, SetVar, Cache, ParseJson, Signature, Hash, Regex, If, Loop, Parallel, Try, Return).
  • Execution Semantics, Constraints, and Security: Covers execution order, guards, compensation, optimistic locking, errors, static constraints and plan limits, and the security model.
  • Cookbook: Covers complete examples such as upsert, a credit guard, an LLM proxy, pagination, parallel execution, a payment saga, and webhook signature verification.
  • Script Resource and Endpoints: Covers the sys structure of the Script resource, the specification of the HTTP endpoints for authoring and execution (/execute), and ScriptLog, the execution log.

If this is your first time, we recommend reading from this page onward in the order Value Expressions, then Statement Catalog. The Cookbook is also worth skimming all the way through.