Calls
A call is a real-time voice session between a user and a LYRE agent. Calls can originate from a web browser (WebRTC), a phone (SIP/PSTN), or an outbound campaign.
Call lifecycle
Every call progresses through a defined set of statuses. Webhooks fire at each transition.
queued
Call created via API. Agent resources are being allocated. For outbound PSTN calls, the number is being dialled.
connecting
WebRTC or SIP signalling in progress. LiveKit room created, participant joining.
ringing
Outbound PSTN only. The destination phone is ringing. Inbound and WebRTC calls skip this state.
in_progress
Call is active. Audio is flowing. The agent is listening, thinking, and speaking. This is where tool calls happen.
completed
Call ended normally. Both parties disconnected gracefully. Recording and transcript processing begins.
failed
Call could not complete. Reasons: provider error, network timeout, compliance block (DNCR match, outside calling hours), or agent error.
Status flow diagram
queued ──> connecting ──> in_progress ──> completed
│ │
│ (outbound)
│ │
└──> ringing ──────┘
│
└──────────────────> failed
Terminal states: completed, failed
Webhook events: call.queued, call.connecting, call.ringing,
call.in_progress, call.completed, call.failedWebRTC browser calls
WebRTC calls connect directly from a web browser to the LYRE agent via LiveKit. This is the lowest-latency option and requires no phone infrastructure.
curl — create a WebRTC call
curl -X POST https://api.lyre.au/v1/calls \
-H "Authorization: Bearer $LYRE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent_abc123",
"type": "web",
"metadata": {
"customer_id": "cust_456",
"page_url": "https://acme.com/support"
}
}'Response
{
"id": "call_xyz789",
"agent_id": "agent_abc123",
"type": "web",
"status": "connecting",
"room_url": "wss://lk.lyre.au",
"token": "eyJhbGciOiJIUzI1NiJ9...",
"created_at": "2026-04-13T10:30:00Z"
}Pass the room_url and token to a LiveKit client in the browser. The token is short-lived (5 minutes) and scoped to the specific room.
Browser — connect with LYRE Web SDK
import { LiveKitRoom } from "@livekit/components-react";
function VoiceWidget({ callToken, roomUrl }) {
return (
<LiveKitRoom
token={callToken}
serverUrl={roomUrl}
connect={true}
audio={true}
video={false}
>
<VoiceAgent />
</LiveKitRoom>
);
}SIP / PSTN phone calls
LYRE supports both inbound and outbound phone calls via SIP trunking. Phone numbers are provisioned through Australian carriers (Symbio, Telstra Wholesale) for local DID numbers.
Inbound calls
Assign a phone number to an agent. When someone calls that number, LYRE automatically connects them to the agent.
Assign a number to an agent
curl -X POST https://api.lyre.au/v1/phone-numbers \
-H "Authorization: Bearer $LYRE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent_abc123",
"area_code": "02",
"type": "local"
}'
# Response:
# { "number": "+61255501234", "agent_id": "agent_abc123", "status": "active" }Outbound calls
Initiate calls from an agent to a phone number. LYRE automatically performs DNCR checking and calling-hours validation before dialling.
Create an outbound call
curl -X POST https://api.lyre.au/v1/calls \
-H "Authorization: Bearer $LYRE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent_abc123",
"type": "phone",
"to": "+61412345678",
"from": "+61255501234",
"metadata": { "campaign_id": "camp_789" }
}'failed with a compliance_block reason.Call recording
When recording is enabled on the agent, LYRE records the full call audio. Recordings are stored in Vultr Object Storage in Sydney (syd1) for Australian data residency.
| Setting | Value | Description |
|---|---|---|
| format | OGG Opus | High quality, small file size |
| channels | Stereo (dual) | Agent on left channel, caller on right |
| retention | 90 days (default) | Configurable per-tenant, 30-365 days |
| storage | Sydney (syd1) | Vultr Object Storage, S3-compatible |
Get recording URL
curl https://api.lyre.au/v1/calls/call_xyz789/recording \
-H "Authorization: Bearer $LYRE_API_KEY"
# Response:
# {
# "url": "https://syd1.vultrobjects.com/lyre-recordings/call_xyz789.ogg",
# "duration_ms": 145000,
# "size_bytes": 1240000,
# "expires_at": "2026-04-13T11:30:00Z"
# }Recording URLs are pre-signed and expire after 1 hour. Request a fresh URL as needed.
Transcripts
LYRE generates a full transcript for every call. Transcripts are available within seconds of call completion and include speaker labels, timestamps, and tool call events.
Get transcript
curl https://api.lyre.au/v1/calls/call_xyz789/transcript \
-H "Authorization: Bearer $LYRE_API_KEY"
# Response:
# {
# "call_id": "call_xyz789",
# "segments": [
# {
# "speaker": "agent",
# "text": "G'day! This is Ava from Acme Solar. How can I help?",
# "start_ms": 0,
# "end_ms": 3200
# },
# {
# "speaker": "user",
# "text": "Hi, I'd like a quote for solar panels.",
# "start_ms": 3800,
# "end_ms": 6100
# },
# {
# "speaker": "agent",
# "type": "tool_call",
# "tool": "check_pricing",
# "args": { "suburb": "Bondi" },
# "start_ms": 6200,
# "end_ms": 7100
# }
# ]
# }Call events and webhooks
Register a webhook URL in the dashboard to receive real-time events for every call state change.
| Event | Fired when |
|---|---|
| call.queued | Call created, waiting for resources |
| call.connecting | WebRTC/SIP signalling started |
| call.ringing | Outbound PSTN call ringing |
| call.in_progress | Audio flowing, conversation active |
| call.completed | Call ended normally |
| call.failed | Call failed (includes reason code) |
| transcript.ready | Full transcript processed and available |
| recording.ready | Recording processed and available |
API operations
| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/calls | Create a new call (WebRTC or phone) |
| GET | /v1/calls | List calls (filterable by agent, status, date) |
| GET | /v1/calls/:id | Get call details |
| POST | /v1/calls/:id/end | Force-end an active call |
| GET | /v1/calls/:id/transcript | Get call transcript |
| GET | /v1/calls/:id/recording | Get pre-signed recording URL |
Next: Australian compliance →