> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lehar.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Place an outbound call

> Fires one outbound phone call, server-to-server. **Requires an `X-API-KEY` credential** — bearer logins and agent-session tokens are rejected even though they can carry `sessions:write`. Answers `200` with the call record; the call may not have dialled yet. The agent must be published and `channel=voice`. Scope `sessions:write`.



## OpenAPI

````yaml /api-reference/openapi.json post /calls
openapi: 3.1.0
info:
  title: Lehar API
  version: v0
  description: >-
    Customer-facing REST API for the Lehar voice-AI platform. Platform-admin
    endpoints are intentionally excluded from this reference. Regenerate with
    `npm run sync:openapi`.
servers:
  - url: https://api.lehar.ai/ca/api/v0
security:
  - ApiKeyAuth: []
  - BearerAuth: []
paths:
  /calls:
    post:
      tags:
        - Calls
      summary: Place an outbound call
      description: >-
        Fires one outbound phone call, server-to-server. **Requires an
        `X-API-KEY` credential** — bearer logins and agent-session tokens are
        rejected even though they can carry `sessions:write`. Answers `200` with
        the call record; the call may not have dialled yet. The agent must be
        published and `channel=voice`. Scope `sessions:write`.
      operationId: create_call_ca_api_v0_calls_post
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - agent_id
                - to_number
              additionalProperties: false
              properties:
                agent_id:
                  type: string
                  description: A published voice agent.
                to_number:
                  type: string
                  description: Destination in E.164, e.g. +919876543210.
                callee_name:
                  type: string
                  maxLength: 128
                from_phone_number_id:
                  type: string
                  description: Caller ID to dial from.
                custom_variables:
                  type: object
                  description: >-
                    Scalar values substituted into the agent's prompt. Max 64
                    keys, 30 KB total.
                  additionalProperties:
                    type:
                      - string
                      - number
                      - boolean
                      - 'null'
                metadata:
                  type: object
                  description: Opaque JSON echoed back. Max 16 KiB.
                idempotency_key:
                  type: string
                  pattern: ^[A-Za-z0-9_.:-]{1,128}$
                  description: >-
                    A repeat of the same key returns 409 instead of dialling
                    twice.
                call_config:
                  type: object
                  properties:
                    idle_timeout_warning:
                      type: integer
                      description: >-
                        Seconds of caller silence after the agent stops
                        speaking, before it nudges. Must be < idle_timeout_end,
                        or the call ends before the nudge can play.
                    idle_timeout_end:
                      type: integer
                      description: >-
                        Seconds of caller silence before hangup, counted from
                        when the agent last stopped speaking. The nudge restarts
                        this window, so total silence before hangup is roughly
                        idle_timeout_warning + idle_timeout_end.
                    max_call_length:
                      type: integer
                      maximum: 3600
                      description: >-
                        Seconds; caps the whole call. Max 3600 (60 minutes);
                        unset defaults to this ceiling, and a higher value is
                        rejected with 400.
                    call_retry_config:
                      type: object
                      properties:
                        retry_count:
                          type: integer
                          minimum: 0
                          maximum: 9
                        retry_busy:
                          type: integer
                          description: Minutes to wait before retrying a busy outcome.
                        retry_not_picked:
                          type: integer
                          description: Minutes to wait before retrying a no_answer outcome.
                        retry_failed:
                          type: integer
                          description: Minutes to wait before retrying any other failure.
                    call_time:
                      type: object
                      description: Permitted calling window; re-checked on every retry.
                      properties:
                        call_start_time:
                          type: string
                          example: '10:00'
                        call_end_time:
                          type: string
                          example: '19:00'
                        timezone:
                          type: string
                          example: Asia/Kolkata
                smart_formatter:
                  type: object
                  description: >-
                    Accepted and echoed back for contract compatibility, but NOT
                    applied to the call.
            example:
              agent_id: agent_sales_hi
              to_number: '+919876543210'
              callee_name: Jane
              custom_variables:
                company: Acme
              idempotency_key: crm-lead-8821
              call_config:
                max_call_length: 600
                call_retry_config:
                  retry_count: 2
                  retry_not_picked: 30
                call_time:
                  call_start_time: '10:00'
                  call_end_time: '19:00'
                  timezone: Asia/Kolkata
      responses:
        '200':
          description: >-
            The call record. `to_number` is never echoed — only
            `to_number_masked`.
          content:
            application/json:
              example:
                call_id: call_01EXAMPLE
                customer_id: customer_01EXAMPLE
                agent_id: agent_sales_hi
                status: queued
                outcome: null
                sub_status: null
                error: null
                to_number_masked: +9198****3210
                callee_name: Jane
                from_number: '+911140000000'
                from_phone_number_id: pn_01EXAMPLE
                custom_variables:
                  company: Acme
                call_config:
                  max_call_length: 600
                smart_formatter: {}
                scheduled_for: null
                attempt_count: 0
                session_id: null
                created_at: '2026-08-11T09:00:00Z'
                updated_at: '2026-08-11T09:00:00Z'
                completed_at: null
        '402':
          description: Insufficient credits
        '403':
          description: Not an API-key credential, or the agent is not yours
        '409':
          description: Duplicate idempotency_key
        '503':
          description: Call orchestration temporarily unavailable
      security:
        - ApiKeyAuth: []
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY
    BearerAuth:
      type: http
      scheme: bearer

````