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

# Create Outbound Call

> Place an outbound phone call using a Yappr agent (default), or — with `type: "web"` — mint a short-lived browser session token for an in-browser voice call via the `@goyappr/client` SDK. A phone call requires $3+ balance and an active Yappr phone number; if server capacity is fully utilized it is queued automatically and returns HTTP 202. A web session does not place a call and is not queued — it returns a token the visitor's browser uses to connect.




## OpenAPI

````yaml POST /calls
openapi: 3.1.0
info:
  title: Yappr API
  description: >
    Create and manage AI voice agents, purchase phone numbers, configure tools,
    and initiate calls — all via REST.
  version: 1.0.0
  contact:
    url: https://goyappr.com
servers:
  - url: https://api.goyappr.com
    description: Production
security:
  - apiKey: []
paths:
  /calls:
    post:
      tags:
        - Calls
      summary: Create outbound call, or mint a web-call session
      description: >
        Place an outbound phone call using a Yappr agent (default), or — with
        `type: "web"` — mint a short-lived browser session token for an
        in-browser voice call via the `@goyappr/client` SDK. A phone call
        requires $3+ balance and an active Yappr phone number; if server
        capacity is fully utilized it is queued automatically and returns HTTP
        202. A web session does not place a call and is not queued — it returns
        a token the visitor's browser uses to connect.
      operationId: createCall
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - agent_id
              properties:
                type:
                  type: string
                  enum:
                    - phone
                    - web
                  default: phone
                  description: >
                    Call channel. Omit or `"phone"` places a normal outbound
                    phone call (requires `to` and `from`).

                    `"web"` mints a short-lived, single-use browser session
                    token instead of dialing — no call is

                    placed until the visitor's browser connects via the
                    `@goyappr/client` SDK. For `"web"`, only

                    `agent_id` is used (`to`/`from` are ignored) and the 201
                    response is a session object.
                agent_id:
                  type: string
                  format: uuid
                to:
                  type: string
                  example: '+972501234567'
                  description: >
                    Destination phone number in strict E.164 format.


                    **Validation rules** (enforced at API and DB layers):

                    - Must match `^\+[1-9][0-9]{7,14}$` — leading `+`, 8–15
                    digits, no spaces or dashes.

                    - Israeli numbers (`+972…`) must be exactly 12 or 13
                    characters total (`+972` followed by an 8-digit landline or
                    9-digit mobile).

                    - Must differ from `from`.


                    Malformed numbers are rejected with `400 INVALID_TO_NUMBER`
                    — no row is written to the database, no carrier dial is
                    attempted, and no capacity is consumed.
                from:
                  type: string
                  example: '+972551234567'
                  description: >
                    Your active Yappr phone number in strict E.164 format. Same
                    validation rules as `to`. Malformed numbers are rejected
                    with `400 INVALID_FROM_NUMBER`.
                variables:
                  type: object
                  additionalProperties:
                    type: string
                  description: >-
                    Key-value pairs injected as template variables into the
                    agent's system prompt (e.g. {{LeadName}}).
                  example:
                    LeadName: David Cohen
                    OrderNumber: ORD-1234
                metadata:
                  type: object
                  description: >
                    Arbitrary key-value data attached to the call log record.
                    Forwarded in real-time to every tool webhook as
                    `call_metadata` so tool receivers (Make.com scenarios, n8n
                    workflows, custom edge functions) can route updates back to
                    the right CRM record without a secondary GET /calls/{id}
                    fetch. Ideal for carrying IDs like appointment_id,
                    contact_id, calendar_id. Not injected into the agent's
                    system prompt.


                    **Flow agents — contract callout.** Flow agents can
                    reference `{{metadata.<key>}}` tokens inside `args_template`
                    values. Missing keys render to an empty string at runtime
                    with no save-time or dispatch-time warning, so always check
                    the agent's `flow_config.metadata.custom_metadata_keys`
                    before placing the call and ensure every key in that array
                    is supplied here.


                    **Reserved keys.** The five platform-supplied tokens (`id`,
                    `direction`, `agent_number`, `user_number`, `agent_name`)
                    are emitted by the platform at call start and cannot be
                    overridden — using any of them as a key here is a `400
                    INVALID_METADATA_RESERVED_KEY`. Pick a different name for
                    your custom field.
                  example:
                    appointment_id: ghl-apt-abc123
                    calendar_id: ghl-cal-xyz789
                    contact_id: ghl-contact-def456
                allowed_origins:
                  type: array
                  items:
                    type: string
                  description: >-
                    Web sessions only (`type: web`). Optional list of browser
                    origins permitted to use the minted session (e.g.
                    `https://app.example.com`).
                  example:
                    - https://app.example.com
      responses:
        '200':
          description: >
            Call blocked because the destination is on the company's Do-Not-Call
            list.

            A `call_logs` row is recorded with `status: "dnc_blocked"` (so
            analytics +

            webhooks pick it up), but no carrier leg is established and no
            minutes

            are charged. To allow this number again, remove its DNC entry via

            `DELETE /do-not-call/{id}`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  call_id:
                    type: string
                    format: uuid
                    nullable: true
                  status:
                    type: string
                    example: dnc_blocked
                  agent_id:
                    type: string
                    format: uuid
                  to:
                    type: string
                  from:
                    type: string
                  message:
                    type: string
                  dnc_reason:
                    type: string
                    nullable: true
                  started_at:
                    type: string
                    format: date-time
                  ended_at:
                    type: string
                    format: date-time
        '201':
          description: >
            Phone call initiated (`type: phone`), or web-call session minted
            (`type: web`).
          content:
            application/json:
              schema:
                oneOf:
                  - title: Phone call initiated
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                        description: call_log ID
                      status:
                        type: string
                      agent_id:
                        type: string
                        format: uuid
                      to:
                        type: string
                      from:
                        type: string
                      created_at:
                        type: string
                        format: date-time
                  - title: Web-call session minted
                    type: object
                    properties:
                      type:
                        type: string
                        example: web
                      token:
                        type: string
                        description: >-
                          Single-use session credential (prefix `wcs_`). Hand to
                          the browser; the SDK presents it as the
                          `x-yappr-web-token` header. Never exposes your API
                          key.
                        example: wcs_9g6-_LauzTgtv8nU31p8un0xk6H-cyUmqD1NEov_0Pk
                      expires_at:
                        type: string
                        format: date-time
                        description: Token expiry (~5 minutes after mint).
                      agent_id:
                        type: string
                        format: uuid
                      agent_name:
                        type: string
                      connection:
                        type: object
                        description: >-
                          Everything the browser SDK needs — pass straight to
                          `startSession({ token, connection })`.
                        properties:
                          base_url:
                            type: string
                          web_call_url:
                            type: string
                          turn_credentials_url:
                            type: string
                          api_key:
                            type: string
                            description: Public/anon key (safe in a browser).
        '202':
          description: >-
            Call queued (server at capacity — will be placed automatically when
            a slot opens)
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    format: uuid
                    description: queue entry ID
                  status:
                    type: string
                    example: queued
                  agent_id:
                    type: string
                    format: uuid
                  to:
                    type: string
                  from:
                    type: string
                  queue_position:
                    type: integer
                  queued_at:
                    type: string
                    format: date-time
                  expires_at:
                    type: string
                    format: date-time
                  message:
                    type: string
        '400':
          description: >
            Bad request. The `code` field identifies the specific failure:

            - `INVALID_TO_NUMBER` — `to` is not a valid E.164 number, or is a
            malformed Israeli number (`+972` not followed by exactly 8 or 9
            digits).

            - `INVALID_FROM_NUMBER` — `from` is malformed, or is not an active
            Yappr number on your account.

            - Self-call (`to` equals `from`), inactive agent, missing required
            field, etc.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: Insufficient balance (minimum $3 required)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Concurrent call limit reached for your plan
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
        code:
          type: string
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: >-
        Your Yappr API key (e.g. `ypr_live_...`). Generate one in the dashboard
        under **Settings → API Keys**.

````