---
title: "Simulate a call"
method: POST
path: "/test/calls"
tags: ["Test mode"]
---

# Simulate a call

`POST /test/calls`

## Request

- Base URL: `https://api.hypamoon.com/api/v1`
- URL: `https://api.hypamoon.com/api/v1/test/calls`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://app.hypamoon.com/oauth/authorize`, token URL `https://api.hypamoon.com/oauth/token`, scopes: `calls:read`)

Test mode only: runs a simulated call on one of your test numbers, with a transcript and a summary, and sends the real webhooks (call.completed, and call.summary.ready when there is a summary). A simulated caller talks to your own assistant, which answers with the same instructions, knowledge and tools as on a real call; tools are not executed. caller_goal (optional, at most 300 characters) says what the caller wants; without it the caller asks something that fits the scenario (reservation, callback_request, question). The scenario missed is a call nobody picked up: no transcript, no summary. Nothing reaches the carrier. The first 10 simulated calls per day are free; after that each one is deducted from the prepaid balance of your live project, billed per use (402 test_free_replies_used without balance or saved card). Send it with your test key; a live key gets 403 test_key_required. At most 30 simulated calls per hour per test project.

## Request body

- TestCallInput
  - `number_id` string, uuid, required: The id of one of your test numbers, from GET /numbers.
  - `scenario` 'reservation' | 'callback_request' | 'question' | 'missed', required: What happens in the call: reservation, callback_request, question, missed. missed has no transcript and no summary, so only call.completed is sent.
  - `from` string: Optional: the caller, a fictional number from +447700900000 to +447700900999.
  - `caller_goal` string

## Response `201`

The simulated call, as GET /calls/{id} returns it.

- CallDetail: A call with its transcript and summary.
  - `id` string, uuid, required: The id of the call.
  - `direction` 'inbound' | 'outbound' | 'null', nullable, required: inbound, or outbound for a call your assistant made with POST /calls.
  - `from` string, nullable, required: The caller, in E.164.
  - `to` string, nullable, required: The number that was called, in E.164.
  - `status` string, nullable, required: The status as we track it: ringing, active, completed, missed, failed, voicemail, ai_handled. New values may be added; treat an unknown value like completed.
  - `created_at` string, date-time, nullable, required: When the call reached us.
  - `started_at` string, date-time, nullable, required: When the call started.
  - `answered_at` string, date-time, nullable, required: When the platform picked up. With a call plan the platform always picks up first, so this does not prove a person answered.
  - `ended_at` string, date-time, nullable, required: When the call ended.
  - `duration_sec` integer, nullable, required: The length of the call in seconds.
  - `hangup_cause` string, nullable, required: Why the call ended, as reported by the carrier, like normal_clearing.
  - `has_summary` boolean, required: Whether the call has a summary. Fetch it with GET /calls/{id}.
  - `summary_ready_at` string, date-time, nullable, required: When the summary of a recorded call was ready. Empty for a call handled by the voice AI; look at has_summary instead.
  - `test` boolean, required: true for a simulated call from POST /test/calls or POST /calls with a test key (test mode). Also in webhooks, so you can keep test traffic apart.
  - `outbound` object, nullable, required: The request behind an outbound call started with POST /calls.
    - `status` 'queued' | 'ringing' | 'in_progress' | 'completed' | 'failed' | 'no_answer' | 'busy', required: How the outbound call went: queued (not dialled yet), ringing, in_progress (answered), completed, failed, no_answer or busy. An answering machine counts as no_answer, with answered_by machine. Only moves forward.
    - `answered_by` 'human' | 'machine' | 'null', nullable, required: Who picked up, as far as answering machine detection could tell; null when nobody answered or before it is known.
    - `voicemail_left` boolean, required: Whether the assistant left a message on an answering machine.
    - `on_voicemail` 'hangup' | 'leave_message', required: What you asked the assistant to do when an answering machine picks up.
    - `max_duration_sec` integer, required: The cap on the length of the call you asked for, in seconds.
    - `reference` string, nullable, required: Your own reference from POST /calls.
    - `metadata` object, required: Your own metadata from POST /calls.
    - `error` string, nullable, required: With status failed: a short code, like carrier_rejected, assistant_start_failed or unallocated_number. Otherwise null.
    - `purpose` 'transactional' | 'marketing', required: Why the call was made, as sent with POST /calls (transactional when left out). A marketing call was only placed on recorded consent.
  - `transcript` string, nullable, required: The transcript. Only here, never in a webhook.
  - `summary` Summary, required: The summary of a call.
    - `text` string, nullable, required: The summary in a few sentences.
    - `topics` string[], required: What the call was about.
    - `sentiment` 'positive' | 'neutral' | 'negative' | 'null', nullable, required: The mood of the caller.
    - `action_items` string[], required: What someone has to do after this call.
    - `next_step` string, nullable, required: The agreed next step, if any.

## Other responses

- `400`: Bad Request: invalid_json.
- `401`: Unauthorized: unauthorized, missing_api_key, invalid_api_key, api_key_revoked, project_deleted.
- `402`: Payment Required: test_free_replies_used.
- `403`: Forbidden: project_not_enabled, key_mode_mismatch, missing_scope, verification_required, test_key_required.
- `404`: Not Found: not_found.
- `422`: Unprocessable Content: validation_failed.
- `429`: Too Many Requests: rate_limited.
- `500`: Internal Server Error: internal_error.
- `503`: Service Unavailable: service_unavailable.

---

[API](https://skmtc.dev/hypamoon/apis/hypamoon-api.md) · [All operations](https://skmtc.dev/hypamoon/apis/hypamoon-api/llms.txt) · [OpenAPI document](https://skmtc.dev/hypamoon/apis/hypamoon-api/revisions/9f0b90004c06?raw)
