Rumatadocs
Browse documentation

Connect backends and workflows

How private workflows, API keys, backends and storage call each other, including publication, credentials, results and identity.

Step-by-step guidance.

Before you start

  • A managed backend and a saved workflow in the same factory.

Connect in this order

  1. Save the workflow, then read `getWorkflowVersions`.
  2. Call `publishIntegrationWorkflow` with the `versionId` and the `deploymentRevision` as `expectedRevision`. It pins that version with private execution and removes broad grants. Keys cannot run drafts; `debugWorkflowRequest` tests drafts.
  3. Call `provisionApiKey` with a `name`, the `factoryId` and an explicit `expiresAt`, and without `groupIds`. It creates the factory’s storage if it does not exist yet.
  4. Bind the returned secret name to a backend environment variable, and configure the returned `workflowGatewayBaseUrl` and `storageApiBaseUrl`.
  5. Call the workflow through the starter’s client.

API keys and groups

ItemContract
`expiresAt`Required. Within one year, or `null` for no expiry.
StorageThe key is stored in project secrets and returned by name, with `groupIds` and its metadata.
Default groupWith no `groupIds`, it joins `<factoryId>_api_key_user_group`: `read`, `write` and `deepRead` on factory storage, plus execute and results (136) on every current and future workflow in the factory, including children. Workflows stay private and need no per-workflow grants.
Custom groupsNonempty `groupIds` replace the default and get no automatic grants. `grantGroupAccess` uses 8 for execution or 136 for execution plus results and status, including called child workflows.
Revocation`revokeApiKey` revokes access. Renewal is not automatic.

Never make a workflow public to bypass permissions.

Call a workflow from a backend

The starter’s typed `src/workflows/client.ts` wraps `POST /wf/<workflowId>/trigger` with the `rumata-api-key` header and `{input: ...}`. The envelope is `{workflowRunId, status, result?, error?}`.

OptionEffect
NoneInherits the saved response mode, synchronous when unset.
`{async:true}`Background job. Returns a run ID to poll.
`{async:false}`Overrides a saved async mode.
  • HTTP 200 alone does not mean completion. `queued`, `running` and `waiting` are pending even on HTTP 200.
  • A terminal file-producing agent returns `result:{output,files}`, and its output schema describes `output`. Without files the result is direct.
  • Use `workflowOutput(run.result)` from the starter, validate the payload and preserve files. Do not assume `result.pages` or other application fields exist.

Return a completed result

`status()` reads once. When an endpoint must return completed output, submit asynchronously once, save the run ID, then call `waitForSuccess(runId, {timeoutMs, signal})`.

ts
const { workflowRunId } = await workflows.submit(workflowId, input, { async: true });
await saveRunId(job.id, workflowRunId);
const run = await workflows.waitForSuccess(workflowRunId, { timeoutMs: 60_000, signal });
return workflowOutput(run.result);
  • `waitForSuccess` returns only `succeeded`, or throws a safe failure, cancellation or deadline error. Map failure to a non-2xx response and keep the run ID.
  • Never resubmit after an uncertain response.
  • Keep 202 plus one-shot status reads for endpoints that intentionally expose background jobs.

Call a backend from a workflow

Use `getBackendService.endpoints.production`, a separate backend-scoped key, and an HTTP node header `rumata-api-key:{secretRef:'<name>'}`. The gateway strips credentials and caller-supplied identity, then supplies the authenticated `x-rumata-api-key-id`. Service-only routes can require the expected key ID. Trust this identity only behind the managed gateway.