sphoroVOICEdocs
Markdown

Workflows

The work that happens because of a conversation, after it. Book the slot, update the CRM, send the confirmation, call your webhook. Six step types, run in order, with each step able to read what the ones before it produced.

When to use one

A workflow is the smallest of the three automation tools, and usually the right one.

You wantReach for
Something done after this callA workflow
Something done during the call, spoken back to the callerA function
A second call tomorrow if this one failedA journey

The six step types

TypeDoes
book_appointmentReserves a slot on a calendar, and can offer alternatives when the requested one is taken.
update_crmWrites the outcome onto a contact record.
send_emailSends one email — the confirmation, the summary, the follow-up.
trigger_webhookOne HTTP request to your own systems. The escape hatch: anything not covered by the five others.
query_dbRuns one of your account's named queries. A step names a query; it never supplies SQL.
setComputes a value into the run's data, for later steps to read.

Creating one

POST/v1/workflows
Shell
curl -s -X POST https://voice.sphoro.com/v1/workflows \
  -H "Authorization: Bearer $SPHORO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "After a booking call",
    "steps": [
      { "id": "slot", "type": "book_appointment",
        "input": {"start": "{{appointment_start}}", "service": "{{service}}"} },
      { "id": "crm",  "type": "update_crm",
        "input": {"phone": "{{to_number}}", "fields": {"last_outcome": "{{outcome}}"}} },
      { "id": "mail", "type": "send_email",
        "input": {"to": "{{email}}", "subject": "Your appointment is confirmed",
                  "text": "See you on {{appointment_start}}."} }
    ]
  }'
FieldTypeDescription
name
required
stringWhat you call it.
steps
required
arrayRun in order. Each has an id, a type and an input.
id
required
stringOn a step. Names it, and is how later steps address what it produced.
type
required
stringOn a step. One of the six above.
input
optional
objectOn a step. Rendered against the run's data, so {{…}} reads the input the run started with and anything earlier steps produced.

Running one

POST/v1/workflows/{id}/runs
Shell
curl -s -X POST https://voice.sphoro.com/v1/workflows/$WORKFLOW_ID/runs \
  -H "Authorization: Bearer $SPHORO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "input": {
      "to_number": "+919876543210",
      "email": "priya@example.com",
      "appointment_start": "2026-09-15T10:30:00+05:30",
      "service": "cleaning",
      "outcome": "booked"
    }
  }'
GET/v1/workflows/{id}/runs
Shell
curl -s https://voice.sphoro.com/v1/workflows/$WORKFLOW_ID/runs \
  -H "Authorization: Bearer $SPHORO_API_KEY"

workflow.run.completed and workflow.run.failed fire when a run ends — see webhooks. A run carries its per-step results, so a failure names the step rather than the workflow.

Wiring it to a finished call

Two ways, and which you want depends on whether the call is part of a longer sequence.

WayHow
From your own webhook handlerSubscribe to call.analysed, then POST /v1/workflows/{id}/runs with the extracted fields as the input. Explicit, and you decide which calls qualify.
From inside a journeyAn actions node names the workflow by id and passes the execution's data as its input. See journeys.
Shell
# From a call.analysed handler.
curl -s -X POST https://voice.sphoro.com/v1/workflows/$WORKFLOW_ID/runs \
  -H "Authorization: Bearer $SPHORO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input": {"outcome": "booked", "to_number": "+919876543210"}}'
Use extractions as the input. The whole point of typed extraction fields is that they are the workflow's arguments: outcome, amount_agreed, callback_number. A workflow driven off a summary string is a workflow parsing prose.

Editing and removing

GET/v1/workflows
PATCH/v1/workflows/{id}
DELETE/v1/workflows/{id}

Steps replace whole on a patch, like every other list in this API — read, change, send the whole array back.

What the connectors are wired to

The calendar, CRM, mailer and query catalogue are configured on your account rather than in the workflow. A step says "book an appointment"; where that booking lands is a connector Sphoro Voice sets up with you. That is why query_db names a query rather than carrying SQL — the statement is defined once, against your database, and a workflow can only choose among the ones that exist.

If a connector you need is not wired up, trigger_webhook gets you there today: it posts to any endpoint of yours, and your side does the work. Talk to us about the rest.