Vapi · Arazzo Workflow

Vapi Assistant Outbound Call End to End

Version 1.0.0

Create an assistant, provision a Vapi phone number, place an outbound call, and poll until it ends.

1 workflow 3 source APIs 1 provider
View Spec View on GitHub AIVoice AIVoice AgentsConversational AITelephonyReal-TimeTranscriptionText-to-SpeechLLMAgentsMCPArazzoWorkflows

Provider

vapi-ai

Workflows

assistant-phone-outbound-call
Stand up an assistant, get a phone number, dial a customer, and watch the call.
Chains assistant creation, phone number provisioning, outbound call creation, and a status poll loop that branches on the call's terminal state.
4 steps inputs: apiToken, areaCode, customerNumber, firstMessage, name, systemPrompt outputs: assistantId, callId, callStatus, cost, endedReason, phoneNumberId
1
createAssistant
AssistantController_create
Create the voice AI assistant that will handle the outbound call.
2
provisionNumber
PhoneNumberController_create
Provision a free Vapi-managed phone number in the desired area code and bind it to the newly created assistant.
3
createCall
CallController_create
Place an outbound call from the provisioned number to the customer using the assistant.
4
pollCall
CallController_findOne
Read the call status and branch: loop back while the call is still active, and finish once it reaches the ended terminal state.

Source API Descriptions

Arazzo Workflow Specification

vapi-ai-assistant-phone-outbound-call-workflow.yml Raw ↑
arazzo: 1.0.1
info:
  title: Vapi Assistant Outbound Call End to End
  summary: Create an assistant, provision a Vapi phone number, place an outbound call, and poll until it ends.
  description: >-
    The complete outbound voice campaign flow. It creates a voice AI assistant,
    buys a free Vapi-managed phone number bound to that assistant, places an
    outbound call from the number to a customer, and then polls the call until
    it reaches a terminal status. Every step spells out its request inline so the
    flow can be read and executed without opening the underlying OpenAPI
    description.
  version: 1.0.0
sourceDescriptions:
- name: assistantsApi
  url: ../openapi/vapi-assistants-api-openapi.yml
  type: openapi
- name: phoneNumbersApi
  url: ../openapi/vapi-phone-numbers-api-openapi.yml
  type: openapi
- name: callsApi
  url: ../openapi/vapi-calls-api-openapi.yml
  type: openapi
workflows:
- workflowId: assistant-phone-outbound-call
  summary: Stand up an assistant, get a phone number, dial a customer, and watch the call.
  description: >-
    Chains assistant creation, phone number provisioning, outbound call
    creation, and a status poll loop that branches on the call's terminal state.
  inputs:
    type: object
    required:
    - apiToken
    - name
    - firstMessage
    - systemPrompt
    - customerNumber
    properties:
      apiToken:
        type: string
        description: Vapi private API key used as a Bearer token.
      name:
        type: string
        description: A human-readable name for the assistant.
      firstMessage:
        type: string
        description: The opening message the assistant speaks.
      systemPrompt:
        type: string
        description: The system prompt that shapes the assistant's behavior.
      customerNumber:
        type: string
        description: The destination phone number in E.164 format to dial.
      areaCode:
        type: string
        description: Desired North American area code for the new Vapi number.
        default: "415"
  steps:
  - stepId: createAssistant
    description: Create the voice AI assistant that will handle the outbound call.
    operationId: AssistantController_create
    parameters:
    - name: Authorization
      in: header
      value: Bearer $inputs.apiToken
    requestBody:
      contentType: application/json
      payload:
        name: $inputs.name
        firstMessage: $inputs.firstMessage
        model:
          provider: openai
          model: gpt-5.4
          messages:
          - role: system
            content: $inputs.systemPrompt
        voice:
          provider: azure
          voiceId: andrew
    successCriteria:
    - condition: $statusCode == 201
    outputs:
      assistantId: $response.body#/id
  - stepId: provisionNumber
    description: >-
      Provision a free Vapi-managed phone number in the desired area code and
      bind it to the newly created assistant.
    operationId: PhoneNumberController_create
    parameters:
    - name: Authorization
      in: header
      value: Bearer $inputs.apiToken
    requestBody:
      contentType: application/json
      payload:
        provider: vapi
        numberDesiredAreaCode: $inputs.areaCode
        assistantId: $steps.createAssistant.outputs.assistantId
        name: $inputs.name
    successCriteria:
    - condition: $statusCode == 201
    outputs:
      phoneNumberId: $response.body#/id
  - stepId: createCall
    description: >-
      Place an outbound call from the provisioned number to the customer using
      the assistant.
    operationId: CallController_create
    parameters:
    - name: Authorization
      in: header
      value: Bearer $inputs.apiToken
    requestBody:
      contentType: application/json
      payload:
        name: $inputs.name
        assistantId: $steps.createAssistant.outputs.assistantId
        phoneNumberId: $steps.provisionNumber.outputs.phoneNumberId
        customer:
          number: $inputs.customerNumber
    successCriteria:
    - condition: $statusCode == 201
    outputs:
      callId: $response.body#/id
      callStatus: $response.body#/status
  - stepId: pollCall
    description: >-
      Read the call status and branch: loop back while the call is still active,
      and finish once it reaches the ended terminal state.
    operationId: CallController_findOne
    parameters:
    - name: Authorization
      in: header
      value: Bearer $inputs.apiToken
    - name: id
      in: path
      value: $steps.createCall.outputs.callId
    successCriteria:
    - condition: $statusCode == 200
    outputs:
      callStatus: $response.body#/status
      endedReason: $response.body#/endedReason
      cost: $response.body#/cost
    onSuccess:
    - name: callEnded
      type: end
      criteria:
      - context: $response.body
        condition: $.status == 'ended'
        type: jsonpath
    - name: stillActive
      type: goto
      stepId: pollCall
      criteria:
      - context: $response.body
        condition: $.status != 'ended'
        type: jsonpath
  outputs:
    assistantId: $steps.createAssistant.outputs.assistantId
    phoneNumberId: $steps.provisionNumber.outputs.phoneNumberId
    callId: $steps.createCall.outputs.callId
    callStatus: $steps.pollCall.outputs.callStatus
    endedReason: $steps.pollCall.outputs.endedReason
    cost: $steps.pollCall.outputs.cost