---
title: "Save call flow draft"
method: PUT
path: "/v2/api/numbers/{number}/call_flow/draft"
tags: ["Phone Numbers"]
---

# Save call flow draft

`PUT /v2/api/numbers/{number}/call_flow/draft`

## Request

- Base URL: `https://api.withallo.com`
- URL: `https://api.withallo.com/v2/api/numbers/{number}/call_flow/draft`
- Auth: API key in header `Authorization`

Creates or updates the working draft of a phone number's call flow. The draft is validated leniently and is not live until published. Optimistic concurrency: pass the `lock_version` returned by a previous read to detect a concurrent edit, and `base_published_version` to detect a publish that happened mid-edit.

## Path parameters

- `number` string, required

## Request body

- object
  - `definition` object, required: The call flow tree document (opaque; camelCase keys).
  - `schema_version` integer, required: Must match the server's current call flow schema version.
  - `lock_version` integer, nullable: The `lock_version` of the draft you are updating; omit or null to upsert without a concurrency check.
  - `base_published_version` integer, nullable: The published version your edit is based on; a mismatch means someone published mid-edit (409).
  - `engine_subset` 'NESTED_IVR' | 'FULL_FLOW', nullable: `FULL_FLOW` runs the whole tree on live calls. `NESTED_IVR` runs only the root phone menu: its keys that lead to a nested menu, a condition or a voicemail node do nothing. Send `FULL_FLOW` for flows you build through the API. When omitted, it is inferred from the nodes: `FULL_FLOW` only if the flow has a business-hours, contact-property, country-code or send-SMS node, otherwise `NESTED_IVR`. A line whose flow is already `FULL_FLOW` keeps it.

## Response `200`

The saved draft

- object
  - `data` CallFlow: A version of a phone number's call flow.
    - `id` string, nullable: The call flow version ID. Null for a synthesized (never-persisted) flow.
    - `flow_id` string, nullable: The parent call flow ID. Null for a synthesized flow.
    - `version` integer: Monotonic version number within the flow.
    - `status` 'DRAFT' | 'PUBLISHED' | 'SYNTHESIZED': DRAFT (working copy), PUBLISHED (live), or SYNTHESIZED (in-memory representation of a legacy IVR-only line).
    - `lock_version` integer: Optimistic-concurrency token; pass it back on the next draft save.
    - `schema_version` integer: The call flow schema version this definition conforms to.
    - `engine_subset` 'NESTED_IVR' | 'FULL_FLOW': `FULL_FLOW` runs the whole tree on live calls. `NESTED_IVR` runs only the root phone menu: its keys that lead to a nested menu, a condition or a voicemail node do nothing.
    - `number` string, nullable: E.164 of the line this flow routes. Null for a never-persisted SYNTHESIZED flow.
    - `confirmation_url` string, nullable: A link where a signed-in user reviews this draft and publishes it. Present only on a `DRAFT` (a `PUBLISHED` or `SYNTHESIZED` version has nothing to confirm). Use it when a person should approve the change; to go live without one, call `POST /v2/api/numbers/{number}/call_flow/publish`. Treat it as opaque: pass it through verbatim, and never construct or parse it.
    - `entry_node_id` string: The id of the entry node in `definition.nodes`.
    - `definition` object: The call flow tree document (opaque; camelCase keys).

## Other responses

- `400`: Invalid request parameters
- `401`: Invalid or missing API key
- `404`: Resource not found
- `409`: Conflict with existing resource
- `429`: Rate limit exceeded

## Changes

- **2026-11-03** `46c77103dd14`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/withallo/apis/allo-api/changes/v2/api/numbers/:number/call_flow/draft/put.md)

---

[API](https://skmtc.dev/withallo/apis/allo-api.md) - [All operations](https://skmtc.dev/withallo/apis/allo-api/llms.txt) - [OpenAPI document](https://skmtc.dev/withallo/apis/allo-api/revisions/46c77103dd14?raw)
