MallaDocs

Queries and integrations

Connect REST, GraphQL and the CMS, keep secrets on the server and pick static, server or client mode.

User guide

Integrations connect a site to an outside service once. Queries use an integration to fetch data on a page, and bindings read the result as queries.name.data.

Integrations

RESTAny JSON API with a base URL, default headers and none, bearer, basic or API-key auth.
GraphQLAn endpoint plus auth. The schema is introspected once to power autocomplete.
CMSBuilt in, no setup. List and get items with filters, sorts and references.
PostgreSQLAny Postgres (Neon, Supabase, RDS…): parameterized SQL over TLS, read-only queries, up to 1,000 rows.
SupabaseSelect, insert, update, delete and call functions through the REST API, with row-level security.
AirtableList records by view or formula, and create, update or delete them.
Google SheetsRead rows as objects, append rows and update ranges with a service account.
ResendSend transactional email from workflows.
Claude and OpenAIGenerate, summarize and extract text, optionally as JSON matching a schema.

Add one in the Data workspace. Fill in the connection settings, enter the secrets (tokens, passwords, API keys), save, and press Run test under Test connection. Admins create and edit integrations; editors can use them in queries and test them.

What you need

The form labels come from the setting names, so they read like Base url or Ssl.

  • REST: the Base url, and for auth a Bearer token, a basic auth Username and Password, or an API key with its header or query parameter name.
  • GraphQL: the Endpoint, and a Bearer token or an API key if it needs auth.
  • PostgreSQL: Host, Port, Database, User and Password, from your provider’s connection details (in Neon, Connect on the project dashboard; in Supabase, Connect at the top of the project).
  • Supabase: the Project url and an API key from the project’s API settings. The anon key respects row-level security; the service-role key bypasses it, so use it only for server workflows.
  • Airtable: the Base id (the app… part of the base URL) and a Personal access token with data.records:read (and data.records:write to change records) on that base.
  • Google Sheets: the Spreadsheet id from the sheet URL, and a Service account key (JSON) with the sheet shared with the service account email. An API key is enough to read sheets that are public on the web.
  • Resend: a Default from sender on a domain verified in Resend, and an API key; a sending-access key is enough.
  • Claude: an API key from the Claude Console.
  • OpenAI: an API key from the OpenAI platform. Base url can point at any OpenAI-compatible API.
A client query on the published site
BrowserAsks Malla to run the query.
EdgeChecks page access and rate limits.
RunnerDecrypts secrets, calls the API.
Your APINever sees the visitor’s browser.

PostgreSQL

Fill in the host, port, database and user, and the password as a secret. Use a role with only the rights the site needs. Write SQL with $1, $2… placeholders and pass the values in params; values are never pasted into the SQL. Query runs in a read-only transaction, so it cannot change data; Execute can write. Results come back as { rows, rowCount, columns, truncated }: set the response path to rows for a collection list.

Create a query

  1. Pick the integration and operation

    For example REST Request, GraphQL Query or CMS List items.

  2. Fill in the input

    Any input value can be an expression. Read variables to make the query react: vars.search, page.params.slug.

  3. Choose when it runs

    Pick a mode (below). Run it once in the editor to see the result and get autocomplete on its fields.

  4. Narrow the result

    Set a response path such as data.items so queries.products.data is the array you want.

json
{
  "name": "products",
  "integrationId": "int_shop_api",
  "operation": "rest.request",
  "input": {
    "method": "GET",
    "path": "/products",
    "query": { "search": { "$expr": "vars.search" } }
  },
  "responsePath": "data.items",
  "run": { "mode": "client", "on": "load", "debounceMs": 250 }
}

Static, server or client

ModeRunsUse it for
Staticat publish; the result is baked into the HTMLmarketing pages, CMS content, best SEO
Serverper request at the edge, optionally cached for N secondsfresh or personalized data that must still be indexed
Clientin the browser, on load and whenever its inputs change (debounced), or only from workflowssearch, filters, dashboards

Reading a query

  • queries.name.data: the result.
  • queries.name.loading: true while it runs. Bind a spinner’s visibility to it.
  • queries.name.error: { message, code } or null.
  • queries.name.updatedAt: when the last result arrived.

Refetch a client query from a workflow with Refetch query. To run an operation that writes or costs money from a page, use Run server workflow with a server workflow called from pages. Lists show query results with collection lists.