---
title: "Create Conference"
method: POST
path: "/conferences"
tags: ["Conferences"]
---

# Create Conference

`POST /conferences`

## Request

- Base URL: `https://api.pinnacle.sh`
- URL: `https://api.pinnacle.sh/conferences`
- Auth: API key in header `PINNACLE-API-KEY`

Create a conference: a room that calls can be added to. Each participant is an ordinary call.

You can add participants in the same request. Existing calls are added first, so the conference is live before dialed participants answer. With no participants the conference is `waiting` until the first one joins.

Send an `Idempotency-Key` to make dialed participants safe to retry: each one is dialed at most once.

## Headers

- `Idempotency-Key` string

## Request body

- CreateConferenceParams
  - `label` string
  - `max_participants` integer
  - `hold_audio_url` string, uri
  - `speaking_events` boolean: Send `participant.speaking` whenever the active speaker changes. Off by default because it can fire several times a second.
  - `metadata` object
  - `participants` AddParticipantParams[]: Participants to add right away. Existing calls are added first, so the conference is live before dialed participants answer.
    - union: Either dial someone (`to` + `from`) or pull in an existing call (`call_id`). `muted` and `whisper_to` can't be combined.
      - DialParticipantParams: Dial someone new. This creates a new outbound call, exactly like `POST /calls`.
        - `to` string, required: E.164 number to dial.
        - `from` string, required: One of your voice-enabled numbers.
        - `label` string: A name you choose for the participant, unique within the conference. Anywhere a participant is referenced you can use its label instead of its `call_id`. Can't start with `call_` or `leg_`.
        - `muted` boolean
        - `on_hold` boolean
        - `whisper_to` string[]: Only these participants (call IDs or labels) can hear this one; it still hears everyone. `null` means everyone hears it (the default). Stored as call IDs, so relabeling someone doesn't change who hears a whisper.
        - `end_conference_on_leave` boolean
        - `announce` union: Played to a dialed participant when they answer, before they join. Nobody else hears it. If it can't be played, they join without it.
          - Announce0
            - `text` string, required
            - `voice` string: Text-to-speech voice. Defaults to `AWS.Polly.Joanna`.
          - Announce1
            - `url` string, uri, required: Public `https` URL of an audio file.
        - `ring_timeout_secs` integer
        - `record` boolean: Same as `record` on `POST /calls`.
        - `metadata` CallMetadata: String metadata carried on future call events. Maximum serialized size is 2 KB.
      - ExistingCallParticipantParams: Pull in a call your team already has. It must be answered and not in another conference.
        - `call_id` string, required
        - `label` string: A name you choose for the participant, unique within the conference. Anywhere a participant is referenced you can use its label instead of its `call_id`. Can't start with `call_` or `leg_`.
        - `muted` boolean
        - `on_hold` boolean
        - `whisper_to` string[]: Only these participants (call IDs or labels) can hear this one; it still hears everyone. `null` means everyone hears it (the default). Stored as call IDs, so relabeling someone doesn't change who hears a whisper.
        - `end_conference_on_leave` boolean

## Response `201`

Conference created.

- Conference
  - `id` string, required
  - `label` string, nullable, required
  - `status` 'waiting' | 'active' | 'ended', required: - `waiting`: Created, but nobody has joined yet. - `active`: At least one participant has joined. - `ended`: Over. Every participant's call has been hung up.
  - `participant_count` integer, required: Participants currently joined.
  - `max_participants` integer, required
  - `hold_audio_url` string, nullable, required: What participants on hold hear.
  - `speaking_events` boolean, required: Whether `participant.speaking` events are sent when the active speaker changes.
  - `metadata` object, required
  - `created_at` string, date-time, required
  - `started_at` string, date-time, nullable, required
  - `ended_at` string, date-time, nullable, required
  - `ended_reason` 'empty' | 'ended_by_api' | 'participant_ended_it' | 'time_limit' | 'expired_waiting' | 'failed', required: Why a conference ended. A conference never ends just because one person is left. - `empty`: The last participant left. - `ended_by_api`: Ended with `DELETE /conferences/{id}` or the `conference.end` command. - `participant_ended_it`: A participant added with `end_conference_on_leave: true` left. - `time_limit`: Reached the 4-hour limit. - `expired_waiting`: Nobody joined in time. - `failed`: The conference couldn't be started.
  - `participants` Participant[], required
    - `call_id` string, required: The participant is this call; every call API works on it.
    - `conference_id` string, required
    - `label` string, nullable, required
    - `status` 'dialing' | 'ringing' | 'joined' | 'left' | 'failed', required: - `dialing`: A dialed participant whose call hasn't answered yet. - `ringing`: Answered and being connected (or hearing its `announce`). - `joined`: In the conference. - `left`: Hung up or was removed. - `failed`: Never connected (busy, no answer, rejected, or an error).
    - `from` string, nullable, required
    - `to` string, nullable, required
    - `muted` boolean, required: Nobody hears this participant; they still hear everyone.
    - `on_hold` boolean, required: They hear hold audio and nobody hears them.
    - `whisper_to` string[], nullable, required: Call IDs of the only participants who can hear this one, or `null` for everyone.
    - `end_conference_on_leave` boolean, required: When this participant leaves, the conference ends for everyone.
    - `joined_at` string, date-time, nullable, required
    - `left_at` string, date-time, nullable, required
    - `left_reason` 'hangup' | 'removed' | 'busy' | 'no_answer' | 'rejected' | 'failed' | 'conference_ended', required

## Other responses

- `400`: Validation failed. The payload has missing required fields and/or invalid types. <br> See https://zod.dev/error-formatting for more information.
- `401`: The request lacks valid authentication credentials or the provided credentials are invalid. <br> Ensure you're including a valid API key in the request headers and that your account has the necessary permissions to access this endpoint.
- `409`: This action cannot be completed right now because the resource is already being processed or is in a state that does not allow the requested change. Check the latest resource status and try again when it is ready.
- `500`: An unexpected error occurred on Pinnacle's servers while processing your request. <br> If this error persists, please contact support with the request details.
- `502`: One of Pinnacle's providers failed. Please try again later.

---

[API](https://skmtc.dev/pinnacle/apis/pinnacle-2.md) - [All operations](https://skmtc.dev/pinnacle/apis/pinnacle-2/llms.txt) - [OpenAPI document](https://skmtc.dev/pinnacle/apis/pinnacle-2/revisions/45416dadab79?raw)
