Skip to content
Get started

Place a call

call.create(**kwargs) -> CallCreateResponse { call }
POST/call

Place a new outbound call order. Provide either an existing assistant ID or a custom assistant configuration. The call can be scheduled for a specific time or started immediately. A single call order may be resolved over multiple call attempts spanning up to a few days, with automatic retries when voicemail is detected. You can also set concurrency limits and pass prompt variables for dynamic personalization.

ParametersExpand Collapse
phone_number: String

The phone number to call in the E.164 format. Example: +1234567890

assistant: { prompt, background_sound, calendly, 14 more}

You can provide a custom assistant configuration here. If you don't provide an assistant_id, this assistant object will be used for this call.

prompt: String

The prompt to use for the call. This will be given to the LLM (gpt-4.1)

background_sound: :"audio/office.ogg"

The background sound to play during the call. Useful to give the impression that your AI agent is in an office, in the street, or anywhere else you want.

calendly: { connection_id, event_type_id}
connection_id: String

The connection ID representing the link between your Calendly account and Revox.

event_type_id: String

The event type ID representing the event type to schedule. (eg: https://api.calendly.com/event_types/b2330295-2a91-4a1d-bb73-99e7707663d5)

call_retry_config: { calling_windows, max_retry_attempts, timezone}

Configuration for call retry behavior including time windows, delays, and max iterations. If not provided, defaults will be used.

calling_windows: Array[{ calling_window_end_time, calling_window_start_time, retry_delay_seconds}]
calling_window_end_time: String

End time for the calling window in the recipient's timezone (or timezone_override if provided). Format: 'HH:mm' (24-hour) or 'H:mma' (12-hour). Examples: '17:00', '6pm'. Default: '18:00'.

calling_window_start_time: String

Start time for the calling window in the recipient's timezone (or timezone_override if provided). Format: 'HH:mm' (24-hour) or 'H:mma' (12-hour). Examples: '09:00', '10am'. Default: '10:00'.

retry_delay_seconds: Integer

Delay between retry attempts in seconds. Default: 7200 (2 hours).

exclusiveMinimum0
maximum9007199254740991
max_retry_attempts: Integer

Maximum number of call retry attempts. Default: 3.

exclusiveMinimum0
maximum9007199254740991
timezone: String

Optional IANA timezone identifier to override the automatic timezone detection from phone number. If not provided, timezone is determined from the recipient's phone number country code. Examples: 'America/New_York', 'Europe/Paris'.

end_of_call_sentence: String

Optional message to say when the agent decides to end the call.

faq_items: Array[{ answer, question}]

FAQ items to associate with this assistant. When provided, replaces all existing FAQ items.

answer: String
question: String
first_sentence: String

The first sentence to use for the call. This will be given to the LLM

first_sentence_delay_ms: Integer

Delay in milliseconds before speaking the first sentence. Default: 400.

minimum0
maximum9007199254740991
first_sentence_mode: :generated | :static | :none

How the first sentence should be handled. "generated" means the LLM will generate a response based on the first_sentence instruction. "static" means the first_sentence will be spoken exactly as provided. "none" means the agent will not speak first and will wait for the user.

One of the following:
:generated
:static
:none
ivr_navigation_enabled: bool

Enable IVR navigation tools. When enabled, the assistant can send DTMF tones and skip turns to navigate phone menus.

llm_model: { name, type} | { openrouter_model_id, openrouter_provider, type}
One of the following:
class UnionMember0 { name, type }
name: :"gpt-4.1" | :"ministral-3-8b-instruct"
One of the following:
:"gpt-4.1"
:"ministral-3-8b-instruct"
type: :"dedicated-instance"
class UnionMember1 { openrouter_model_id, openrouter_provider, type }
openrouter_model_id: String

The model ID to use from OpenRouter. eg: openai/gpt-4.1

openrouter_provider: String

The provider to use from OpenRouter. eg: nebius, openai, azure, etc.

type: :openrouter

Use a model from OpenRouter.

max_call_duration_secs: Float

The maximum duration of the call in seconds. This is the maximum time the call will be allowed to run.

structured_output_config: Array[{ name, required, type, 2 more}]

The structured output config to use for the call. This is used to extract the data from the call (like email, name, company name, etc.).

name: String
minLength1
required: bool
type: :string | :number | :boolean | 3 more
One of the following:
:string
:number
:boolean
:enum
:date
:datetime
description: String
enum_options: Array[String]
transfer_phone_number: String

Phone number to transfer calls to when users request to speak to a human agent in E.164 format (e.g. +1234567890).

voice: { id, provider, speed}

The voice to use for the call. You can get the list of voices using the /voices endpoint

id: String

The ID of the voice.

minLength1
provider: :cartesia | :elevenlabs

The provider of the voice.

One of the following:
:cartesia
:elevenlabs
speed: Float

The speed of the voice. Range depends on provider: Cartesia 0.6–1.5, ElevenLabs 0.7–1.2. Default is 1.0.

minimum0.6
maximum1.5
voicemail_message: String

If set, when voicemail is detected the agent will speak this message then hang up; if null, hang up immediately.

webhook_url: String

The webhook URL to call when the call is completed.

assistant_id: String

The ID of the assistant to use for this call.

concurrency: { key, max}

Limit the number of concurrent calls for a given concurrency key.

key: String

The key for which you want to limit the number of concurrent calls.

max: Float

The maximum number of concurrent calls to allow for the given concurrency key.

minimum1
force_now: bool

The prompt to use for the call. This will be given to the LLM (gpt-4.1)

from_phone_number: String

The phone number to use for making the call (e.g., +1234567890). If not provided, uses the default trunk.

metadata: Hash[Symbol, String]

Metadata to store with the call.

prompt_variables: Hash[Symbol, String]

Variables to interpolate into the prompt. Wether you use an assistant_id or an assistant object, this will be used to interpolate the variables into the prompt.

scheduled_at: Time | untyped

Schedule the call to start at a specific date and time (ISO 8601 format). If not provided, the call will start immediately.

One of the following:
Time
untyped
ReturnsExpand Collapse
class CallCreateResponse { call }
call: { id, assistant, call_attempts, 16 more}

This represent a call "order" that was requested by the user. A call order can be resolved over multiple call attempts spanning up to a few days.

id: String

The ID of the call.

assistant: { id, background_sound, calendly, 20 more}
id: String
background_sound: :"audio/office.ogg"

The background sound to play during the call. Useful to give the impression that your AI agent is in an office.

calendly: { connection_id, event_type_id}
connection_id: String

The connection ID representing the link between your Calendly account and Revox.

event_type_id: String

The event type ID representing the event type to schedule. (eg: https://api.calendly.com/event_types/b2330295-2a91-4a1d-bb73-99e7707663d5)

call_retry_config: { calling_windows, max_retry_attempts, timezone}

Configuration for call retry behavior including time windows, delays, and max iterations. If not provided, defaults will be used.

calling_windows: Array[{ calling_window_end_time, calling_window_start_time, retry_delay_seconds}]
calling_window_end_time: String

End time for the calling window in the recipient's timezone (or timezone_override if provided). Format: 'HH:mm' (24-hour) or 'H:mma' (12-hour). Examples: '17:00', '6pm'. Default: '18:00'.

calling_window_start_time: String

Start time for the calling window in the recipient's timezone (or timezone_override if provided). Format: 'HH:mm' (24-hour) or 'H:mma' (12-hour). Examples: '09:00', '10am'. Default: '10:00'.

retry_delay_seconds: Integer

Delay between retry attempts in seconds. Default: 7200 (2 hours).

exclusiveMinimum0
maximum9007199254740991
max_retry_attempts: Integer

Maximum number of call retry attempts. Default: 3.

exclusiveMinimum0
maximum9007199254740991
timezone: String

Optional IANA timezone identifier to override the automatic timezone detection from phone number. If not provided, timezone is determined from the recipient's phone number country code. Examples: 'America/New_York', 'Europe/Paris'.

created_at: untyped
end_of_call_sentence: String
first_sentence: String
first_sentence_delay_ms: Integer

Delay in milliseconds before speaking the first sentence. Default: 400.

minimum-9007199254740991
maximum9007199254740991
first_sentence_mode: :generated | :static | :none
One of the following:
:generated
:static
:none
ivr_navigation_enabled: bool

Enable IVR navigation tools. When enabled, the assistant can send DTMF tones and skip turns to navigate phone menus.

llm_model: { name, type} | { openrouter_model_id, openrouter_provider, type}
One of the following:
class UnionMember0 { name, type }
name: :"gpt-4.1" | :"ministral-3-8b-instruct"
One of the following:
:"gpt-4.1"
:"ministral-3-8b-instruct"
type: :"dedicated-instance"
class UnionMember1 { openrouter_model_id, openrouter_provider, type }
openrouter_model_id: String

The model ID to use from OpenRouter. eg: openai/gpt-4.1

openrouter_provider: String

The provider to use from OpenRouter. eg: nebius, openai, azure, etc.

type: :openrouter

Use a model from OpenRouter.

max_call_duration_secs: Float

The maximum duration of the call in seconds. This is the maximum time the call will be allowed to run.

name: String
organization_id: String
prompt: String
structured_output_config: Array[{ name, required, type, 2 more}]

The structured output config to use for the call. This is used to extract the data from the call (like email, name, company name, etc.).

name: String
minLength1
required: bool
type: :string | :number | :boolean | 3 more
One of the following:
:string
:number
:boolean
:enum
:date
:datetime
description: String
enum_options: Array[String]
transfer_phone_number: String

Phone number to transfer calls to when users request to speak to a human agent.

updated_at: untyped
voice: { id, provider, speed}
id: String

The ID of the voice.

minLength1
provider: :cartesia | :elevenlabs

The provider of the voice.

One of the following:
:cartesia
:elevenlabs
speed: Float

The speed of the voice. Range depends on provider: Cartesia 0.6–1.5, ElevenLabs 0.7–1.2. Default is 1.0.

minimum0.6
maximum1.5
voicemail_message: String

If set, when voicemail is detected the agent will speak this message then hang up; if null, hang up immediately.

webhook_url: String

The webhook URL to call when the call is completed.

faq_items: Array[{ answer, question, id, 2 more}]
answer: String
question: String
id: String
needs_human_answer: bool
source: :human | :ai
One of the following:
:human
:ai
pending_faq_count: Float
call_attempts: Array[{ id, answered_at, dial_error, 10 more}]

All call attempts for this call order, ordered by most recent first.

id: String

The ID of the call attempt.

answered_at: untyped

The time the call was answered.

dial_error: :number_non_attributed | :too_many_calls | :busy | 5 more

The SIP error that occurred.

One of the following:
:number_non_attributed
:too_many_calls
:busy
:temporarily_unavailable
:no_answer
:no_international_permission
:precondition_failed
:non_classified_error
ended_at: untyped

The time the call ended.

phone_number: String

The phone number that was called. Formatted in E.164 format. Example: +1234567890

recording_url: String

The URL of the audio recording of the call.

result: :IVR | :voicemail | :human | 2 more
One of the following:
:IVR
:voicemail
:human
:unknown
:"ios-screening-filter"
started_at: untyped

The time the call started.

status: :queued | :ringing | :ongoing | 2 more

The status of the call attempt.

One of the following:
:queued
:ringing
:ongoing
:completed
:error
end_reason: String

Reason for ending the call when ended_by is 'agent'. E.g. 'tool_end_call', 'voicemail', 'transfer', 'ivr_no_navigate'.

ended_by: :agent | :user | :system

Who ended the call: 'agent' (AI agent), 'user' (caller/callee hung up), or 'system' (e.g. max duration limit).

One of the following:
:agent
:user
:system
structured_output: Hash[Symbol, untyped]

The data extracted from the call, using the structured output config from the parent call object.

transcript: Array[{ content, role, tool_arguments, 2 more}]

The transcript of the call.

content: String
role: :user | :assistant | :tool
One of the following:
:user
:assistant
:tool
tool_arguments: Hash[Symbol, untyped] | String
One of the following:
Hash[Symbol, untyped]
String
tool_is_error: bool
tool_name: String
call_retry_config: { calling_windows, max_retry_attempts, timezone}

Configuration for call retry behavior including time windows, delays, and max iterations. If not provided, defaults will be used.

calling_windows: Array[{ calling_window_end_time, calling_window_start_time, retry_delay_seconds}]
calling_window_end_time: String

End time for the calling window in the recipient's timezone (or timezone_override if provided). Format: 'HH:mm' (24-hour) or 'H:mma' (12-hour). Examples: '17:00', '6pm'. Default: '18:00'.

calling_window_start_time: String

Start time for the calling window in the recipient's timezone (or timezone_override if provided). Format: 'HH:mm' (24-hour) or 'H:mma' (12-hour). Examples: '09:00', '10am'. Default: '10:00'.

retry_delay_seconds: Integer

Delay between retry attempts in seconds. Default: 7200 (2 hours).

exclusiveMinimum0
maximum9007199254740991
max_retry_attempts: Integer

Maximum number of call retry attempts. Default: 3.

exclusiveMinimum0
maximum9007199254740991
timezone: String

Optional IANA timezone identifier to override the automatic timezone detection from phone number. If not provided, timezone is determined from the recipient's phone number country code. Examples: 'America/New_York', 'Europe/Paris'.

calls_count: Float

The number of call attempts made.

campaign: { id, name}
id: String
name: String
created_at: untyped

The time the call order was created.

direction: :inbound | :outbound

Whether the call is inbound or outbound.

One of the following:
:inbound
:outbound
first_sentence_delay_ms: Integer

Delay in milliseconds before speaking the first sentence. Default: 400.

minimum-9007199254740991
maximum9007199254740991
from_phone_number: String

The phone number that made the call. Formatted in E.164 format. Example: +1234567890

is_cancelled: bool

DEPRECATED: Whether the call has been cancelled. This is derived from status. Use status instead.

is_completed: bool

DEPRECATED: Whether the call has completed. This is derived from status. Use status instead.

last_call_attempt: { id, answered_at, dial_error, 10 more}

This represent a single call attempt. A call attempt is a single call made to the phone number.

id: String

The ID of the call attempt.

answered_at: untyped

The time the call was answered.

dial_error: :number_non_attributed | :too_many_calls | :busy | 5 more

The SIP error that occurred.

One of the following:
:number_non_attributed
:too_many_calls
:busy
:temporarily_unavailable
:no_answer
:no_international_permission
:precondition_failed
:non_classified_error
ended_at: untyped

The time the call ended.

phone_number: String

The phone number that was called. Formatted in E.164 format. Example: +1234567890

recording_url: String

The URL of the audio recording of the call.

result: :IVR | :voicemail | :human | 2 more
One of the following:
:IVR
:voicemail
:human
:unknown
:"ios-screening-filter"
started_at: untyped

The time the call started.

status: :queued | :ringing | :ongoing | 2 more

The status of the call attempt.

One of the following:
:queued
:ringing
:ongoing
:completed
:error
end_reason: String

Reason for ending the call when ended_by is 'agent'. E.g. 'tool_end_call', 'voicemail', 'transfer', 'ivr_no_navigate'.

ended_by: :agent | :user | :system

Who ended the call: 'agent' (AI agent), 'user' (caller/callee hung up), or 'system' (e.g. max duration limit).

One of the following:
:agent
:user
:system
structured_output: Hash[Symbol, untyped]

The data extracted from the call, using the structured output config from the parent call object.

transcript: Array[{ content, role, tool_arguments, 2 more}]

The transcript of the call.

content: String
role: :user | :assistant | :tool
One of the following:
:user
:assistant
:tool
tool_arguments: Hash[Symbol, untyped] | String
One of the following:
Hash[Symbol, untyped]
String
tool_is_error: bool
tool_name: String
llm_model: { name, type} | { openrouter_model_id, openrouter_provider, type}
One of the following:
class UnionMember0 { name, type }
name: :"gpt-4.1" | :"ministral-3-8b-instruct"
One of the following:
:"gpt-4.1"
:"ministral-3-8b-instruct"
type: :"dedicated-instance"
class UnionMember1 { openrouter_model_id, openrouter_provider, type }
openrouter_model_id: String

The model ID to use from OpenRouter. eg: openai/gpt-4.1

openrouter_provider: String

The provider to use from OpenRouter. eg: nebius, openai, azure, etc.

type: :openrouter

Use a model from OpenRouter.

metadata: Hash[Symbol, String]

Metadata stored with the call.

organization_id: String

The ID of the organization that owns the call.

scheduled_at: untyped

The time the call order is scheduled to start.

status: :initializing | :queued_for_calling | :calling | 4 more

The status of the call.

One of the following:
:initializing
:queued_for_calling
:calling
:scheduled
:completed
:cancelled
:errored
to_phone_number: String

The phone number that received the call. Formatted in E.164 format. Example: +1234567890

Place a call

require "revox"

revox = Revox::Client.new(api_key: "My API Key")

call = revox.call.create(phone_number: "phone_number")

puts(call)
{
  "call": {
    "id": "id",
    "assistant": {
      "id": "id",
      "background_sound": "audio/office.ogg",
      "calendly": {
        "connection_id": "connection_id",
        "event_type_id": "event_type_id"
      },
      "call_retry_config": {
        "calling_windows": [
          {
            "calling_window_end_time": "calling_window_end_time",
            "calling_window_start_time": "calling_window_start_time",
            "retry_delay_seconds": 1
          }
        ],
        "max_retry_attempts": 1,
        "timezone": "timezone"
      },
      "created_at": {},
      "end_of_call_sentence": "end_of_call_sentence",
      "first_sentence": "first_sentence",
      "first_sentence_delay_ms": -9007199254740991,
      "first_sentence_mode": "generated",
      "ivr_navigation_enabled": true,
      "llm_model": {
        "name": "gpt-4.1",
        "type": "dedicated-instance"
      },
      "max_call_duration_secs": 0,
      "name": "name",
      "organization_id": "organization_id",
      "prompt": "prompt",
      "structured_output_config": [
        {
          "name": "x",
          "required": true,
          "type": "string",
          "description": "description",
          "enum_options": [
            "string"
          ]
        }
      ],
      "transfer_phone_number": "transfer_phone_number",
      "updated_at": {},
      "voice": {
        "id": "x",
        "provider": "cartesia",
        "speed": 0.6
      },
      "voicemail_message": "voicemail_message",
      "webhook_url": "webhook_url",
      "faq_items": [
        {
          "answer": "answer",
          "question": "question",
          "id": "id",
          "needs_human_answer": true,
          "source": "human"
        }
      ],
      "pending_faq_count": 0
    },
    "call_attempts": [
      {
        "id": "id",
        "answered_at": {},
        "dial_error": "number_non_attributed",
        "ended_at": {},
        "phone_number": "phone_number",
        "recording_url": "recording_url",
        "result": "IVR",
        "started_at": {},
        "status": "queued",
        "end_reason": "end_reason",
        "ended_by": "agent",
        "structured_output": {
          "foo": "bar"
        },
        "transcript": [
          {
            "content": "content",
            "role": "user",
            "tool_arguments": {
              "foo": "bar"
            },
            "tool_is_error": true,
            "tool_name": "tool_name"
          }
        ]
      }
    ],
    "call_retry_config": {
      "calling_windows": [
        {
          "calling_window_end_time": "calling_window_end_time",
          "calling_window_start_time": "calling_window_start_time",
          "retry_delay_seconds": 1
        }
      ],
      "max_retry_attempts": 1,
      "timezone": "timezone"
    },
    "calls_count": 0,
    "campaign": {
      "id": "id",
      "name": "name"
    },
    "created_at": {},
    "direction": "inbound",
    "first_sentence_delay_ms": -9007199254740991,
    "from_phone_number": "from_phone_number",
    "is_cancelled": true,
    "is_completed": true,
    "last_call_attempt": {
      "id": "id",
      "answered_at": {},
      "dial_error": "number_non_attributed",
      "ended_at": {},
      "phone_number": "phone_number",
      "recording_url": "recording_url",
      "result": "IVR",
      "started_at": {},
      "status": "queued",
      "end_reason": "end_reason",
      "ended_by": "agent",
      "structured_output": {
        "foo": "bar"
      },
      "transcript": [
        {
          "content": "content",
          "role": "user",
          "tool_arguments": {
            "foo": "bar"
          },
          "tool_is_error": true,
          "tool_name": "tool_name"
        }
      ]
    },
    "llm_model": {
      "name": "gpt-4.1",
      "type": "dedicated-instance"
    },
    "metadata": {
      "foo": "string"
    },
    "organization_id": "organization_id",
    "scheduled_at": {},
    "status": "initializing",
    "to_phone_number": "to_phone_number"
  }
}
Returns Examples
{
  "call": {
    "id": "id",
    "assistant": {
      "id": "id",
      "background_sound": "audio/office.ogg",
      "calendly": {
        "connection_id": "connection_id",
        "event_type_id": "event_type_id"
      },
      "call_retry_config": {
        "calling_windows": [
          {
            "calling_window_end_time": "calling_window_end_time",
            "calling_window_start_time": "calling_window_start_time",
            "retry_delay_seconds": 1
          }
        ],
        "max_retry_attempts": 1,
        "timezone": "timezone"
      },
      "created_at": {},
      "end_of_call_sentence": "end_of_call_sentence",
      "first_sentence": "first_sentence",
      "first_sentence_delay_ms": -9007199254740991,
      "first_sentence_mode": "generated",
      "ivr_navigation_enabled": true,
      "llm_model": {
        "name": "gpt-4.1",
        "type": "dedicated-instance"
      },
      "max_call_duration_secs": 0,
      "name": "name",
      "organization_id": "organization_id",
      "prompt": "prompt",
      "structured_output_config": [
        {
          "name": "x",
          "required": true,
          "type": "string",
          "description": "description",
          "enum_options": [
            "string"
          ]
        }
      ],
      "transfer_phone_number": "transfer_phone_number",
      "updated_at": {},
      "voice": {
        "id": "x",
        "provider": "cartesia",
        "speed": 0.6
      },
      "voicemail_message": "voicemail_message",
      "webhook_url": "webhook_url",
      "faq_items": [
        {
          "answer": "answer",
          "question": "question",
          "id": "id",
          "needs_human_answer": true,
          "source": "human"
        }
      ],
      "pending_faq_count": 0
    },
    "call_attempts": [
      {
        "id": "id",
        "answered_at": {},
        "dial_error": "number_non_attributed",
        "ended_at": {},
        "phone_number": "phone_number",
        "recording_url": "recording_url",
        "result": "IVR",
        "started_at": {},
        "status": "queued",
        "end_reason": "end_reason",
        "ended_by": "agent",
        "structured_output": {
          "foo": "bar"
        },
        "transcript": [
          {
            "content": "content",
            "role": "user",
            "tool_arguments": {
              "foo": "bar"
            },
            "tool_is_error": true,
            "tool_name": "tool_name"
          }
        ]
      }
    ],
    "call_retry_config": {
      "calling_windows": [
        {
          "calling_window_end_time": "calling_window_end_time",
          "calling_window_start_time": "calling_window_start_time",
          "retry_delay_seconds": 1
        }
      ],
      "max_retry_attempts": 1,
      "timezone": "timezone"
    },
    "calls_count": 0,
    "campaign": {
      "id": "id",
      "name": "name"
    },
    "created_at": {},
    "direction": "inbound",
    "first_sentence_delay_ms": -9007199254740991,
    "from_phone_number": "from_phone_number",
    "is_cancelled": true,
    "is_completed": true,
    "last_call_attempt": {
      "id": "id",
      "answered_at": {},
      "dial_error": "number_non_attributed",
      "ended_at": {},
      "phone_number": "phone_number",
      "recording_url": "recording_url",
      "result": "IVR",
      "started_at": {},
      "status": "queued",
      "end_reason": "end_reason",
      "ended_by": "agent",
      "structured_output": {
        "foo": "bar"
      },
      "transcript": [
        {
          "content": "content",
          "role": "user",
          "tool_arguments": {
            "foo": "bar"
          },
          "tool_is_error": true,
          "tool_name": "tool_name"
        }
      ]
    },
    "llm_model": {
      "name": "gpt-4.1",
      "type": "dedicated-instance"
    },
    "metadata": {
      "foo": "string"
    },
    "organization_id": "organization_id",
    "scheduled_at": {},
    "status": "initializing",
    "to_phone_number": "to_phone_number"
  }
}