Skip to main content

How to Create and Update CRM Workflows with the Sensei Workflow API (CRM)

Overview The Sensei Workflow API lets you build and update CRM automation workflows programmatically — the same workflows you'd otherwise create by hand in Settings → Workflows.

Before You Begin

You'll need:

  • Access to your CRM's REST endpoint (your CRM administrator can confirm the address).

  • A valid signed-in CRM session identifier.

  • A REST client such as Postman, or the Sensei agent, to send requests.

Who can use this: Any signed-in CRM user can create or update workflows through the API — there's no special add-on permission. The workflow is created as the signed-in user.


⚠️ Warning: Every workflow created through the API starts switched OFF. It will not run until someone turns it on. This is deliberate — it lets you review a generated workflow before it acts on live records. See Turning the Workflow On.


💡 Tip: If a newly created workflow doesn't seem to do anything, that's expected — it was created disabled.


In every example below, replace https://<your-crm-address> with your CRM's address and <session> with your current signed-in session. Every response uses the same envelope: success returns {"success": true, "result": {…}}; a problem returns {"success": false, "error": {"code": "…", "message": "…"}} naming the exact thing to fix.


⚠️ Warning: Sessions expire after a period of inactivity. If a request reports an invalid session, sign in again to get a fresh one and retry.


Steps

Step 1 — Discover Available Modules, Fields, Tokens, and Actions

You never have to guess field names, module names, or merge-token wording — discovery requests tell you exactly what each module supports. Always copy field references and merge tokens exactly as they come back; names differ between instances due to custom fields and white-label labels.


Get Workflow Modules — which modules support workflows:

GET https://<your-crm-address>/crm/restapi.php/getworkflowmodules?sessionName=<session>


json

{   "success": true,   "result": {     "modules": [       { "name": "Potentials", "label": "Intake Opportunities" },       { "name": "Contacts", "label": "Accounts" },       { "name": "Accounts", "label": "Referral Sources" }     ],     "related": { "Potentials": [ { "name": "Accounts", "label": "Referral Sources" } ] }   } }


💡 Tip: "Accounts" is the label for the patients module (internally Contacts); "Referral Sources" is the referral-org module (internally Accounts); "Intake Opportunities" is internally Potentials. Use whichever label discovery returns.


Get Workflow Fields — condition fields and allowed comparisons:

GET https://<your-crm-address>/crm/restapi.php/getworkflowfields?sessionName=<session>&module=Leads

json

{   "success": true,   "result": {     "module": "Leads", "label": "Leads",     "fields": [       { "ref": "Leads.Lead Status", "fieldname": "leadstatus", "label": "Lead Status",         "type": "picklist", "operators": ["is","is not","starts with","ends with","contains","does not contain","has changed","is empty","is not empty"] }     ]   } }

Use the ref value in a condition, and pick an operator only from that field's operators list.


Get Workflow Tokens — merge fields for emails, texts, and tasks:

GET https://<your-crm-address>/crm/restapi.php/getworkflowtokens?sessionName=<session>&module=Leads

json

{   "success": true,   "result": {     "module": "Leads", "label": "Leads",     "tokens": [       { "friendly": "[{Leads.First Name}]", "group": "field", "contexts": ["send_mail.subject","send_mail.content","send_sms.message"] },       { "friendly": "[{Primary Email}]", "group": "email_recipient", "contexts": ["send_mail.to","send_mail.cc","send_mail.bcc"] }     ]   } }


💡 Tip: group: field tokens (e.g. [{Leads.First Name}]) go in subjects, bodies, and task text. group: email_recipient tokens (e.g. [{Primary Email}]) go only in email recipient boxes (to/cc/bcc/reply_to).


Get Workflow Task Types — the five actions and their settings:

GET https://<your-crm-address>/crm/restapi.php/getworkflowtasktypes?sessionName=<session>&module=Leads

Returns the field list and requirements for send_mail, send_sms, send_internal_notification, update_fields, and create_task (see The Five Actions below).


Get Workflows — list existing workflows (searchable):

GET https://<your-crm-address>/crm/restapi.php/getworkflows?sessionName=<session>&search=Sample

Returns each workflow's id, name, module, active state, and edit url. Use a returned id as the workflow_id when updating or enabling a workflow.


Get Workflow SMS Config — text-message settings (only needed for a Send Text action):

GET https://<your-crm-address>/crm/restapi.php/getworkflowsmsconfig?sessionName=<session>&module=Leads

Returns tpn_options and phone_field_options — pick a tpn and one or more phone_field_options values for the Send Text action.


Step 2 — Create a Workflow

Send a POST to createworkflow with the workflow definition. On success you get back a workflow ID, confirmation it's off (active: false), and a link to review it.


Example — runs on every save, with conditions:

POST https://<your-crm-address>/crm/restapi.php/createworkflow?sessionName=<session> Content-Type: application/json


json

{   "module": "Leads",   "name": "Sample - notify on new lead",   "description": "Created via Sensei Workflow API",   "trigger": { "execution_condition": "every_save" },   "conditions": { "groups": [     { "group_condition": "and", "columns": [       { "field": "Leads.First Name", "operator": "is not empty", "value": "" },       { "field": "Leads.Lead Status", "operator": "is", "value": "Cold" }     ] }   ] },   "tasks": [     { "type": "send_mail", "summary": "Email the lead",       "to": "[{Primary Email}]",       "subject": "Welcome [{Leads.First Name}]",       "content": "<p>Hi [{Leads.First Name}] [{Leads.Last Name}].</p>" }   ] }

Response:


json

{   "success": true,   "result": { "workflow_id": 283, "active": false,     "url": "https://<your-crm-address>/crm/index.php?module=Workflows&parent=Settings&view=Edit&record=283" } }

Example — scheduled weekly workflow: Set the trigger to scheduled and provide a recurrence. For a weekly schedule, supply the time and the days_of_week (1 = Monday … 7 = Sunday).


json

{   "module": "Leads",   "name": "Sample - weekly digest",   "description": "Scheduled weekly",   "trigger": { "execution_condition": "scheduled",     "recurrence": { "schedule_type": "weekly", "time": "09:00", "days_of_week": [1, 5] } },   "tasks": [     { "type": "send_internal_notification", "summary": "Weekly review",       "subject": "Weekly lead review", "assigned_user_id": "1" }   ] }

💡 Tip: Other schedule types: hourly, daily (needs time), monthly_by_date (needs time + days_of_month), specific_date (needs time + date as MM-DD-YYYY), and annually (needs time + annual_dates).


The Five Actions

A workflow can carry any combination of these five actions. Every action needs a summary (its Action Title, shown in the editor).

Action (type)

What it does

Key settings

send_mail

Emails a recipient

to, subject (required); cc, bcc, reply_to, from, content

send_sms

Sends a text via your phone service

message, phone_field_ids (required); tpn (from SMS config)

send_internal_notification

Notifies a CRM user/team

subject, assigned_user_id (required)

update_fields

Sets field values on the record

field_value_mapping (required)

create_task

Creates a follow-up activity

todo (required); status, priority, assigned_user_id, due-date timing

  • In the recipient boxes of a Send Mail action, use email_recipient tokens (e.g. [{Primary Email}]), not field tokens.

  • update_fields entries can be a plain value (rawtext), a copy of another field (fieldname), or a computed value (expression).

  • Merge tokens are written in the friendly [{Module.Field}] form; the CRM converts them to the stored form automatically.

Choosing When It Runs (Trigger)

execution_condition

When it runs

first_save

Only when a record is first created

once

The first time a record matches your conditions

every_save

Every time a record is created or edited (default)

scheduled

On a recurring schedule

Setting Conditions (Which Records)

Conditions filter which records a workflow acts on, in two groups:

  • All conditions (group_condition: "and") — every rule must be true.

  • Any conditions (group_condition: "or") — at least one rule must be true.

Each rule is a field ref, an operator valid for that field, and a value. Leave conditions out entirely and the workflow applies to every save of the chosen module.


Step 3 — Review the Workflow

Open the url returned in the create response. It opens the workflow in Settings → Workflows, alongside workflows created by hand, where you can review it exactly like any manually built workflow.


Step 4 — Turn the Workflow On

Because every workflow is created off, enabling it is a separate PATCH to updateworkflow using the workflow ID.

PATCH https://<your-crm-address>/crm/restapi.php/updateworkflow?sessionName=<session> Content-Type: application/json

json

{ "workflow_id": 283, "active": true }

Response:


json

{   "success": true,   "result": { "workflow_id": 283, "active": true,     "url": "https://<your-crm-address>/crm/index.php?module=Workflows&parent=Settings&view=Edit&record=283" } }

⚠️ Warning: Only enable a workflow after reviewing it. To switch it off later, send the same request with "active": false.


Step 5 — Update an Existing Workflow

Use PATCH to updateworkflow with the workflow ID. Only the sections you include are changed — anything omitted is left as-is. If you include tasks, all existing actions are replaced by the ones you send (omit tasks to keep them).

PATCH https://<your-crm-address>/crm/restapi.php/updateworkflow?sessionName=<session> Content-Type: application/json

json

{   "workflow_id": 283,   "tasks": [     { "type": "send_mail", "summary": "Updated email",       "to": "[{Primary Email}]",       "subject": "Updated [{Leads.Last Name}]",       "content": "<p>Updated body for [{Leads.First Name}]</p>" }   ] }


⚠️ Warning: A workflow's module cannot be changed after creation — create a new workflow to target a different module.


Verification / Expected Result

  • A successful create or update returns "success": true with a workflow_id, current active state, and an edit url.

  • The workflow appears in Settings → Workflows, looking and behaving like any workflow built by hand.

  • Newly created workflows show active: false until you explicitly enable them (Step 4).

Troubleshooting / Common Errors

If a request is rejected, the CRM's error.message names the exact thing to fix:

Error code

It usually means…

What to do

INVALID_TOKEN

A [{…}] token doesn't exist for this module

Use a token exactly as Get Workflow Tokens lists it

INVALID_FIELD

A condition field isn't on this module

Re-check Get Workflow Fields

INVALID_COMPARATOR

The operator isn't allowed for that field type

Pick one of the field's listed operators

DUPLICATE_WORKFLOW_NAME

That name already exists in the module

Choose a unique name, or update the existing one

MANDATORY_FIELDS_MISSING

A required piece is missing (name, or an action's summary)

Add the missing item and resend

INVALID_SMS_CONFIG

The text-message settings don't match your provider

Rebuild the Send Text action from Get Workflow SMS Config

INVALID_SESSIONID

Your session expired

Sign in again for a fresh session

Related Resources

Did this answer your question?