GET /catalog needs workflowBuilder.platformActionFields, the community's own field keys for platform-action steps, and permissions, the one permission this API takes, so a caller never has to guess a field name or a capability.platformActionFields is the community's field catalog, not its values.Authorization: Bearer <API_KEY>. The community is taken from the key; no request field selects it, and no key can see another community's catalog because a catalog is not community-specific.workflowBuilder and nothing else.| Failure | Meaning | Recovery |
|---|---|---|
| Missing or invalid key | Rejected before any route handler runs | Send a valid community API key. |
| Admin session token | Sessions are refused: this API cannot use an admin login | Create a key with the workflowBuilder permission. |
Key without workflowBuilder | The key authenticated but may not use the builder | Add the permission, or use another key. |
Key with dataWorkflows only | That permission keeps its event ingest status meaning and grants nothing here | Grant workflowBuilder. |
nodeTypes lists the step types, all eight of them with available: true, including code. platformActionFields lists the field keys a platform-action step may name, split by whether the step reads or writes. permissions is the single permission this API takes.{
"data": {
"nodeTypes": [
{
"type": "http",
"label": "HTTP request",
"sideEffects": true,
"hasBranches": false,
"available": true,
"schema": { "type": "object", "properties": { "type": { "const": "http" } }, "required": ["type", "name", "options"] }
},
{
"type": "code",
"label": "Code",
"sideEffects": true,
"hasBranches": false,
"available": true,
"schema": { "type": "object", "properties": { "type": { "const": "code" }, "options": { "type": "object" } }, "required": ["type", "name", "options"] }
}
],
"triggerTypes": [
{ "type": "webhook", "label": "Webhook", "schema": { "type": "object", "properties": { "type": { "const": "webhook" }, "options": { "type": "object" } }, "required": ["type"] } },
{ "type": "visit-community", "label": "User visits the community", "schema": { "type": "object", "properties": { "type": { "const": "visit-community" }, "options": { "type": "null" } }, "required": ["type"] } }
],
"referenceSyntax": {
"dynamicValue": {
"description": "A field can read an earlier step output. Use a template string or a reference object.",
"template": "{{nodeId.field}}",
"object": { "nodeId": "24 hex characters", "field": "path" }
},
"triggerOutput": "The trigger step id is returned as trigger._id on GET /{workflowId}."
},
"redaction": {
"sentinel": "__REDACTED__",
"description": "Credential values are returned as [\"__REDACTED__\"] and listed in redactedPaths. Send the sentinel back unchanged to keep the stored value."
},
"platformActionFields": {
"note": "Leave fields[].label empty and the API fills the canvas label, or use the label shown here. The label keys the node output, and downstream references must use that label.",
"get": [
{ "key": "total_xp", "label": "Total XP", "source": "builtin" },
{ "key": "total_coins", "label": "Total Coins", "source": "builtin" },
{ "key": "xp", "label": "XP", "source": "builtin" },
{ "key": "coin", "label": "Coins", "source": "builtin" },
{ "key": "tier", "label": "tier", "source": "custom", "fieldType": "string" }
],
"post": [
{ "key": "xp", "label": "XP", "source": "builtin" },
{ "key": "coin", "label": "Coins", "source": "builtin" },
{ "key": "tier", "label": "tier", "source": "custom", "fieldType": "string" }
]
},
"limits": { "maxListLimit": 100, "maxNodesPerImport": 200 },
"permissions": ["workflowBuilder"],
"codeNodes": {
"writable": true,
"description": "Code steps support create, update, duplicate, import and testing."
}
}
}http, platform-action, math, send-email, send-emails, code, router, users-bulk-update. Seven trigger types are returned: time, webhook, visit-community, join-community, custom-field-update, conditions-trigger, event-ingest.platformActionFields.note states the label rule in the API's own words. platformActionFields.get names the keys a read action may use, and platformActionFields.post names the keys a write action may use. Each entry carries the key to store, the label the platform fills in when the write omits one, and whether the field is builtin or custom. A read action accepts total_xp, total_coins, xp and coin; a write action accepts xp and coin; both accept the community's custom fields, so a community-defined field is as usable as xp.200 with a data object. Read the schema for the step type you are about to add and the platformActionFields entry for the field you mean to use, then build the node body from them. Nothing is persisted, so there is no follow-up read to prove this call.sideEffects: true means running the step writes, sends mail, pays, or calls an outside system. hasBranches: true is true only for router, whose branches hold other steps.| Status and code | When | Recovery |
|---|---|---|
401 AUTHENTICATION_REQUIRED | No key, or a key that no longer resolves | Send a valid key. |
401 API_KEY_REQUIRED | A valid admin session was used instead of a key | Use a community API key. |
403 API_KEY_PERMISSION_DENIED | The key lacks workflowBuilder | Grant the permission. |
404 COMMUNITY_NOT_FOUND | The key's community no longer exists | Use a key of an existing community. |
429 RATE_LIMITED | The community's API rate limit was reached | Wait for the window to reset, then retry. |
500 INTERNAL_ERROR | Unexpected failure | Retry with bounded backoff; stop if it persists. |
available and permissions on every call rather than caching a schema for a long session.required list tells you which fields the write refuses to guess.platformActionFields for the action you are using: a read action uses the get list, a write action the post list. A key outside the list is stored as sent and POST /{workflowId}/validate reports UNKNOWN_USER_FIELD as a warning, but the step reads or writes nothing, so take the key from this payload.label in the catalog is the one the platform fills in when a write omits a label. A label you send is kept as sent, and a read step's result is keyed by it, so the label decides how later steps must reference the step. Send the catalog's label unless you have a reason to choose another.Total XP here may be Total Points there: take the label from this payload, not from an example.platformActionFields is per community, because custom fields are. Two communities can return different lists for the same API version.rai_get_node_schema takes a workflowId and returns triggerOutput for it; otherwise read a recorded run to see which payload paths a step can reference.available is a capability gate for the write path. All eight step types are available: true, Code included; unavailableReason appears only when a release turns a type off.options is null for the trigger types that take no options.platformActionFields with source: "custom".limits.maxListLimit is the page-size ceiling for the list endpoints. A larger limit is refused rather than clamped.POST /{workflowId}/validate will warn about. A step can match every schema here and still be worth a warning, and a write that matches no schema can be the one that warns.POST / creates a workflow with its trigger.POST /{workflowId}/nodes adds a step, using this catalog's schema for its options.POST /{workflowId}/validate for the advisory check on the stored workflow before a test or a deploy.curl --location 'https://api.returning.ai/v1/workflow-builder/data-workflows/catalog' \
--header 'Authorization: Bearer <API_KEY>'{
"data": {
"nodeTypes": [
{
"type": "http",
"label": "HTTP request",
"sideEffects": true,
"hasBranches": false,
"available": true,
"schema": {
"type": "object",
"required": [
"type",
"name",
"options"
]
}
}
],
"triggerTypes": [
{
"type": "webhook",
"label": "Webhook",
"schema": {
"type": "object",
"required": [
"type"
]
}
}
],
"referenceSyntax": {
"dynamicValue": {
"template": "{{nodeId.field}}"
},
"triggerOutput": "The trigger node id is returned as trigger._id."
},
"redaction": {
"sentinel": "__REDACTED__"
},
"platformActionFields": {
"note": "Leave fields[].label empty and the API fills the canvas label, or use the label shown here. The label keys the node output, and downstream references must use that label.",
"get": [
{
"key": "total_xp",
"label": "Total XP",
"source": "builtin"
},
{
"key": "total_coins",
"label": "Total Coins",
"source": "builtin"
},
{
"key": "xp",
"label": "XP",
"source": "builtin"
},
{
"key": "coin",
"label": "Coins",
"source": "builtin"
}
],
"post": [
{
"key": "xp",
"label": "XP",
"source": "builtin"
},
{
"key": "coin",
"label": "Coins",
"source": "builtin"
}
]
},
"limits": {
"maxListLimit": 100,
"maxNodesPerImport": 200
},
"permissions": [
"workflowBuilder"
],
"codeNodes": {
"writable": true,
"description": "Code steps support create, update, duplicate, import and testing."
}
}
}