Docs
Automations

Save a new automation

POSThttps://api.norreach.app/v1/automations

Saves a flow (nodes and edges in the automation builder's own format) as a draft. Nothing runs until it is activated; compile_error says what would stop that. Every contact, list, segment, AI caller and campaign the flow names must be this workspace's (422 otherwise).

campaigns:writeRole must allow: campaigns.editOperation id: create_automation
POST/automations
curl -X POST "https://api.norreach.app/v1/automations" \
  -H "Authorization: Bearer $NORREACH_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Webinar follow-up",
  "flow": {
    "nodes": [
      {
        "id": "start",
        "type": "trigger",
        "position": {
          "x": 0,
          "y": 0
        },
        "data": {
          "nodeType": "trigger",
          "triggerType": "manual_contacts",
          "label": "Picked contacts",
          "config": {
            "audience": {
              "lists": [
                {
                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                }
              ]
            }
          }
        }
      },
      {
        "id": "hello",
        "type": "action",
        "position": {
          "x": 0,
          "y": 160
        },
        "data": {
          "nodeType": "action",
          "actionType": "send_email",
          "label": "Intro email",
          "config": {
            "subject": "Nurses for the summer",
            "template": "Hi {{first_name}}, …"
          }
        }
      }
    ],
    "edges": [
      {
        "id": "start-hello",
        "source": "start",
        "target": "hello",
        "source_handle": null,
        "target_handle": null
      }
    ],
    "settings": {
      "stopOnReply": true
    }
  }
}'
Save a new automation
{
  "id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
  "object": "automation",
  "name": "Webinar follow-up",
  "status": "draft",
  "trigger": "manual_contacts",
  "node_count": 2,
  "compiled_step_count": 0,
  "created_at": "2026-11-04T09:12:33.120Z",
  "flow": {
    "nodes": [
      {
        "id": "start",
        "type": "trigger",
        "position": {
          "x": 0,
          "y": 0
        },
        "data": {
          "nodeType": "trigger",
          "triggerType": "manual_contacts",
          "label": "Picked contacts",
          "config": {
            "audience": {
              "lists": [
                {
                  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
                }
              ]
            }
          }
        }
      },
      {
        "id": "hello",
        "type": "action",
        "position": {
          "x": 0,
          "y": 160
        },
        "data": {
          "nodeType": "action",
          "actionType": "send_email",
          "label": "Intro email",
          "config": {
            "subject": "Nurses for the summer",
            "template": "Hi {{first_name}}, …"
          }
        }
      }
    ],
    "edges": [
      {
        "id": "start-hello",
        "source": "start",
        "target": "hello",
        "source_handle": null,
        "target_handle": null
      }
    ],
    "settings": {
      "stopOnReply": true,
      "name": "Webinar follow-up"
    }
  },
  "compile_error": null
}

Authorizations

Authorizationstringheaderrequired

Bearer authentication: send Authorization: Bearer <key>, with an API key or an OAuth access token. The key needs the scope campaigns:write. API keys and scopes

Headers

Idempotency-Keystringheader

Any unique string (≤ 255). The same key with the same request returns the first answer for 24 hours.

Body

application/json

namestringrequired
flowobjectrequired

An automation's flow graph.

Show child attributes
flow.nodesobject[]required
Show child attributes
flow.nodes[].idstringrequired
flow.nodes[].typestring
flow.nodes[].positionobject
Show child attributes
flow.nodes[].position.xnumberrequired
flow.nodes[].position.ynumberrequired
flow.nodes[].dataobjectrequired

The node: nodeType (trigger, action or condition), triggerType / actionType / conditionType, label and config — the flow builder's own format.

flow.edgesobject[]required
Show child attributes
flow.edges[].idstringrequired
flow.edges[].sourcestringrequired
flow.edges[].targetstringrequired
flow.edges[].source_handlestring | null

yes / no on a condition's outgoing edges.

flow.edges[].target_handlestring | null
flow.settingsobject

Flow settings (schedule, days, timezone, stopOnReply …).

Response

201application/json— Save a new automation

idstring (uuid)required

An id (UUID).

object"automation"required
namestringrequired
statusstringrequired

draft, active, paused or archived (stopped).

triggerstring | nullrequired

What starts the flow (e.g. manual_contacts, landing_form).

node_countintegerrequired
compiled_step_countintegerrequired

Steps in the program the engine runs (set when it is activated).

created_atstringrequired

RFC 3339 UTC timestamp with milliseconds.

flowobject | nullrequired
compile_errorstring | nullrequired

Why the flow can't be activated as it is (null = it compiles).

Errors

Errors are application/problem+json with a stable code.

StatusCodeMeaning
400bad_requestThe request couldn't be read.
400unknown_fieldThe request has a field this operation doesn't know.
401unauthorizedA valid API key is required.
403insufficient_scopeThis API key doesn't have the scope this operation needs.
403feature_not_enabledThe API isn't switched on for this workspace.
403role_forbiddenThe key's creator's role can't do this.
409idempotency_in_progressA request with this Idempotency-Key is still running.
413too_largeThe request body is too large.
422validation_failedThe request has invalid fields.
422idempotency_mismatchThis Idempotency-Key was used with a different request.
429rate_limitedToo many requests. Slow down and try again.
500server_errorSomething went wrong on our side.
503unavailableThe API isn't available right now. Try again shortly.