Create and assign a serverless IVR call flow through REST, without hosting a webhook server.
serverless
The claim
The vendored REST spec’s POST /api/fabric/resources/call_flows requires one field, title, and takes relayml, “The calling SWML document this Call Flow should execute”. That sentence is the serverless part: the flow executes the document, and nothing of yours serves it. POST /api/fabric/resources/{id}/phone_routes requires phone_route_id and handler, an enum of calling and messaging. Its prose says “incoming calls or messages”; the enum is what the API accepts. The document has four top-level verbs. They are answer, a prompt whose schema requires play and collects one digit, a switch whose schema requires variable and case, and hangup. You reach the REST calls as client.fabric.call_flows.create and client.fabric.resources.assign_phone_route.
POST /api/fabric/resources/call_flows
{"title": "Ridgeline Cycles IVR",
"relayml": {"version": "1.0.0", "sections": {"main": [
{"answer": {}},
{"prompt": {"play": "say:Thanks for calling ...", "max_digits": 1, "initial_timeout": 8}},
{"switch": {"variable": "prompt_value",
"case": {"1": [{"connect": {"to": "+1555...", "timeout": 25}}],
"2": [{"connect": {"to": "+1555...", "timeout": 25}}]},
"default": [{"play": {"url": "say:Sorry, that was not an option. Goodbye."}}]}},
{"hangup": {}}]},
"flow_data": {"generated_by": "signalwire-recipes", "recipe": "build-an-ivr-without-a-server"}}
POST /api/fabric/resources/<resource_id>/phone_routes
{"phone_route_id": "<id of your number>", "handler": "calling"}
The SWML prompt reference documents prompt_value as the variable that holds what the prompt collected, so switch reads it by name. SWMLService.add_verb raises SchemaValidationError for a verb the bundled schema rejects, so a wrong field fails on your machine, not after deployment. number_id looks the number up with the spec’s filter_number and compares exactly.
Limitations
You prove the document and the requests. What the caller hears, and whether a desk answers, are the platform’s side of a live call.
The spec describes flow_data as “Call Flow Builder state, stored as an opaque JSON object”, and says to send it with relayml or send neither. The script sends a small descriptor beside the document; the document is the source.
What to change first
Add a third desk to DESKS under "3" and run the verifier. The switch assertion fails, because the verifier pins two cases. Add the case there too. The same document then deploys with three.