Test mode
Test mode runs the whole API without placing calls or sending messages. Requests, checks and events work the same as in live mode. Test phone numbers give you each call outcome on demand.
Test keys
Test keys start with ll_test_. They are in the dashboard next to your live keys. The key decides the mode. There is no mode parameter on requests.
- Test and live objects are kept apart. A live key gets
not_foundfor a test object, and a test key gets it for a live object. - Every object and event created in test mode has
livemodefalse. - Subaccounts have their own test keys. The
Liveleg-Accountheader works the same way with a test key.
What runs in test mode
- Validation, scopes, idempotency and every error code.
- Compliance checks: calling hours, your test do-not-call list, consent records, state call limits and opt-out words. Calling hours use the real clock and the lead's state. A test call to a Pennsylvania lead at 7 am Eastern is blocked the same way as a live one.
- Dial sessions with several lines per agent, detection, phone tree navigation and callbacks, using the outcomes of the test numbers below.
- Agent tokens and
@liveleg/voice. A bridged test call connects the agent to a test line that plays a short greeting. - Recordings and transcripts. Each bridged test call gets a sample recording and a sample transcript.
- Webhooks. Endpoints created with a test key receive test events only. Endpoints created with a live key receive live events only.
- Call records and usage, with billed seconds and amounts as they would be billed.
What does not run
- No calls are placed and no messages are sent.
- Numbers bought with a test key are test numbers. They cannot receive real calls and are not billed.
- Ports, caller name updates and registrations are not filed.
- Nothing is invoiced. Test usage never counts toward the minimum spend.
- Subaccounts created with a test key are not reviewed. They show the same requirements, any uploaded file is marked verified, and each capability turns active a few seconds later.
Test phone numbers
Use these numbers as leads, as to on a single call, or as a message recipient. Any other number behaves like +12025550100. In live mode these numbers are rejected with invalid_request.
| Number | What happens |
|---|---|
+12025550100 | A person answers after 3 seconds and says hello. amd.completed with human, then call.bridged. The line stays connected until the agent hangs up. |
+12025550101 | A voicemail greeting answers. amd.completed with machine_voicemail. The line is dropped. |
+12025550102 | A phone tree answers with machine_ivr. With ivr set, the navigator takes two menu steps, waits 20 seconds on hold and a person picks up. call.bridged carries ivr_path and hold_seconds. Without ivr, the line is dropped. |
+12025550103 | A call screener asks who is calling, with machine_screener. With the screener option on and a consent record with recorded_voice true, the agent's line plays and a person picks up. Otherwise the agent is connected to the screener. |
+12025550104 | The line is answered and nobody speaks. machine_silent. |
+12025550105 | Busy. leg.failed with cause busy. |
+12025550106 | Rings with no answer until the ring time ends. leg.no_answer, and the leg ends with result no_answer. |
+12025550107 | Disconnected. The lookup returns line_status disconnected and the lead is skipped with call.blocked, reason line_disconnected and rule lookup.line_status. |
+12025550108 | A person answers, then asks not to be called again. The number goes on your test do-not-call list with dnc.added, and summary.ready has opt_out_requested true. |
+12025550109 | Replies STOP to any message. message.received, then dnc.added with source text_reply. |
The area code 500 has no state. Send state on each test lead. The state sets the calling hours and the recording rule for the call.
Run a test session
Load three test leads, connect the agent with a token from your test key, and start a session with three lines. The person on +12025550100 is bridged, the voicemail is dropped and the busy line fails.
curl https://api.liveleg.dev/v1/lead_lists/lst_roofing_tx/leads \
-H "Authorization: Bearer $LIVELEG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"leads": [
{ "phone": "+12025550100", "state": "TX", "name": "Dana Ruiz" },
{ "phone": "+12025550101", "state": "TX" },
{ "phone": "+12025550105", "state": "TX" }
]
}'// LIVELEG_API_KEY holds your ll_test_ key.
const res = await fetch('https://api.liveleg.dev/v1/lead_lists/lst_roofing_tx/leads', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.LIVELEG_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
leads: [
{ phone: '+12025550100', state: 'TX', name: 'Dana Ruiz' },
{ phone: '+12025550101', state: 'TX' },
{ phone: '+12025550105', state: 'TX' },
],
}),
});
const data = await res.json();import os, requests
# LIVELEG_API_KEY holds your ll_test_ key.
data = requests.post(
"https://api.liveleg.dev/v1/lead_lists/lst_roofing_tx/leads",
headers={"Authorization": f"Bearer {os.environ['LIVELEG_API_KEY']}"},
json={
"leads": [
{"phone": "+12025550100", "state": "TX", "name": "Dana Ruiz"},
{"phone": "+12025550101", "state": "TX"},
{"phone": "+12025550105", "state": "TX"},
],
},
).json() curl https://api.liveleg.dev/v1/dial_sessions \
-H "Authorization: Bearer $LIVELEG_API_KEY" \
-d agent_id=agt_114 \
-d lead_list_id=lst_roofing_tx \
-d lines=3const res = await fetch('https://api.liveleg.dev/v1/dial_sessions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.LIVELEG_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
agent_id: 'agt_114',
lead_list_id: 'lst_roofing_tx',
lines: 3,
}),
});
const session = await res.json();import os, requests
session = requests.post(
"https://api.liveleg.dev/v1/dial_sessions",
headers={"Authorization": f"Bearer {os.environ['LIVELEG_API_KEY']}"},
json={
"agent_id": "agt_114",
"lead_list_id": "lst_roofing_tx",
"lines": 3,
},
).json() {
"id": "evt_0Tq55Wn2",
"type": "call.bridged",
"created_at": "2026-11-03T15:10:04.880Z",
"livemode": false,
"account_id": "acc_ridgeline",
"data": {
"call_id": "cal_0Tq5Pz81",
"dial_session_id": "dls_0Tq4Ab",
"agent_id": "agt_114",
"to": "+12025550100",
"speech_ended_to_bridge_ms": 960,
"legs_canceled": 1
}
} Going live
- Swap the test key for a live key. Request and response formats are the same.
- Create the live objects again: numbers, caller ID pools, agents, lead lists and webhook endpoints. Test IDs do not carry over.
- Live endpoints get a new signing secret. Update it on your server.
- Live calling starts when your account review is done. Each subaccount needs its own review. See Subaccounts.