calls

Place an outbound AI phone call. Two request shapes: freeform (target_phone + brief) or structured (target_phone + intent + slots). See the guide above for the 422 slot-retry loop. Either shape takes the optional disclosure and record_call fields, which change or turn off the call's opening notice and its recording, and voice. A refusal below places no call and costs nothing. Two answers below are not refusals, because they cannot say whether a call was placed: 409 idempotency_state_unknown and 502. Their entries say how to recover.

post/calls

Request

  • Base URL
    https://api.voygr.tech
  • URL
    https://api.voygr.tech/calls
  • Auth
    API key in header X-API-Key

Headers

Idempotency-Keystring nullable

Makes a retry safe: one fresh value (a UUID) per call you intend to place, in printable ASCII. For 24 hours the same key and body return the original response with the header Idempotent-Replayed: true, and nothing is dialed or charged again. After a 402, 429, 502, 503 or 403 account_suspended, retry with the same key; a 400, other 403 or 422 is replayed as is, so fix the body and use a new key. Without the header every request is a new call.

X-Client-Surfacestring

Optional. Names the listing or document this call was placed from (for example llms-txt). Telemetry only: it never affects auth, billing or the call.

Request body

ask_user_mode'any' | 'stream' | 'webhook'

A mid-call question always goes to the ask_user event on GET /calls/{call_id}/events. When this key has a webhook registered whose events include ask_user (the default), it also goes to a signed POST to it, with the same request_id. Answer via POST /calls/{call_id}/answer. any (default) and stream behave the same. webhook adds a check before dialing: with no webhook registered on this key the call is refused with 422 ask_user_channel_required.

briefstring nullable

Plain-language task for the call. Required for freeform requests.

intent'inquiry' | 'info_gathering' | 'issue_resolution' | 'booking' nullable

Structured path only. booking places the call to make the reservation; no booking record is stored.

kind'restaurant_booking' | 'restaurant_cancel' | 'doctor_appointment' | 'hotel_booking' | 'concierge' | 'other'
language'auto' | 'de' | 'en' | 'es' | 'fr' | 'hi' | 'it' | 'ja' | 'nl' | 'pl' | 'pt' | 'ru' | 'sr' | 'tr'

ISO 639-1 code or auto. Unsupported codes are refused with 422 unsupported_language.

record_callboolean nullable

false: the call's audio is never recorded and the opening sentence drops its recording clause; transcript_full is still kept, and transcript_status reads final as soon as the transcript exists. Default true. Outside English and Spanish, false requires disclosure: false, because those default sentences announce a recorded line.

slotsobject nullable

Structured path only. Required slots per intent. inquiry: target_phone, question. info_gathering: target_phone, questions. issue_resolution: target_phone, issue_description. booking: target_phone, name, date (YYYY-MM-DD), time (HH:MM, 24-hour), party_size.

suggestion_idstring nullable

Links this call to a card from POST /v1/places/suggest. Freeform path only. The card must be yours and at most 7 days old, and target_phone must equal its phone_e164; otherwise 422 SUGGESTION_NOT_FOUND, SUGGESTION_PHONE_MISMATCH or SUGGESTION_WITH_SLOTS_UNSUPPORTED. It changes nothing about how the call is placed.

target_phonestring nullable

E.164 format.

Example request

{
  "disclosure": {
    "company_name": "Acme Health",
    "on_behalf_of": "Example Insurance",
    "purpose": "to verify your practice's directory information",
    "mention_ai": true
  },
  "target_phone": "+15551234567"
}

Response

Call created and dialing, returned only by a deployment that dials immediately (api.voygr.tech answers 202). The envelope depends on the request path: freeform returns CallResponse (a call wrapper, so the ID is call.call_id), structured returns the flat SkillRunResponse (top-level call_id). Either way, poll GET /calls/{call_id} afterwards; that response is the same whichever path created the call.

OR

Example response

{
  "call": {
    "call_id": "c_abc123",
    "customer_id": "cus_xyz",
    "target_phone": "+15551234567"
  },
  "credits_charge_on_success": 10
}

Changes

    • breaking

      removed subschema #1: Freeform subschema #2: Structured from the request body anyOf list

    • info

      header request parameter Idempotency-Key list-of-types was widened by adding types null

    • info

      for the header request parameter Idempotency-Key, the type was generalized from string to no type

    • info

      request property list-of-types was widened by adding types null to media type application/json

    • info

      added to the response body anyOf list for the response status

    • info

      added to the response body anyOf list for the response status

    • info

      removed from the response body oneOf list for the response status

    • info

      removed from the response body oneOf list for the response status

    • info

      added the new optional header request parameter X-Client-Surface

    • info

      added the required property / to the response with the status