cURL Examples
Corrected 2026-08-24 against the real API (backend/internal/publicapi/routes.go). The previous version of this file used the wrong host, the wrong base path, fake ID formats, and one endpoint shape (/webhooks/test) that never existed — see ../changelog.md.
Setup
export VOICEMATRIX_API_KEY="vm_live_your_key_here"
export VOICEMATRIX_BASE_URL="https://api.voicematrix.ai/api/v1/ext"Calls
List recent calls
curl -H "X-API-Key: $VOICEMATRIX_API_KEY" \
"$VOICEMATRIX_BASE_URL/calls?limit=10"Filter by status
curl -H "X-API-Key: $VOICEMATRIX_API_KEY" \
"$VOICEMATRIX_BASE_URL/calls?status=completed&limit=20"Valid status values: completed, missed, failed.
Filter by date range
curl -H "X-API-Key: $VOICEMATRIX_API_KEY" \
"$VOICEMATRIX_BASE_URL/calls?from_date=2026-08-01&to_date=2026-08-24"Get call details
curl -H "X-API-Key: $VOICEMATRIX_API_KEY" \
"$VOICEMATRIX_BASE_URL/calls/<call-uuid>"IDs are real UUIDs (e.g. 550e8400-e29b-41d4-a716-446655440000) — not a call_... prefix format.
Make an outbound call
curl -X POST "$VOICEMATRIX_BASE_URL/calls" \
-H "X-API-Key: $VOICEMATRIX_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"to": "+972501234567",
"agent_id": "<agent-uuid>",
"metadata": { "campaign": "summer_sale", "source": "crm" }
}'Send Idempotency-Key on this one — a retried request with the same key won't place a second call. See ../authentication.md#idempotency.
Leads
List / filter
curl -H "X-API-Key: $VOICEMATRIX_API_KEY" \
"$VOICEMATRIX_BASE_URL/leads?status=new&limit=50"Get one
curl -H "X-API-Key: $VOICEMATRIX_API_KEY" \
"$VOICEMATRIX_BASE_URL/leads/<lead-uuid>"Create
curl -X POST "$VOICEMATRIX_BASE_URL/leads" \
-H "X-API-Key: $VOICEMATRIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Smith",
"phone": "+972507654321",
"email": "[email protected]",
"source": "referral",
"notes": "Referred by an existing customer, interested in the premium plan."
}'Update status
curl -X PATCH "$VOICEMATRIX_BASE_URL/leads/<lead-uuid>" \
-H "X-API-Key: $VOICEMATRIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "qualified", "notes": "Follow-up scheduled for next week" }'Agents
curl -H "X-API-Key: $VOICEMATRIX_API_KEY" "$VOICEMATRIX_BASE_URL/agents"
curl -H "X-API-Key: $VOICEMATRIX_API_KEY" "$VOICEMATRIX_BASE_URL/agents/<agent-uuid>"Full agent lifecycle (create/update/publish) is in ../resources/agents.md.
Webhooks
Register
curl -X POST "$VOICEMATRIX_BASE_URL/webhooks" \
-H "X-API-Key: $VOICEMATRIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/voicematrix",
"events": ["call.ended", "lead.created"]
}'Real event names are call.started, call.ended, lead.created, lead.updated, agent.error — not call.completed, which was never a real event. Full catalog in ../webhooks.md.
List / delete
curl -H "X-API-Key: $VOICEMATRIX_API_KEY" "$VOICEMATRIX_BASE_URL/webhooks"
curl -X DELETE -H "X-API-Key: $VOICEMATRIX_API_KEY" "$VOICEMATRIX_BASE_URL/webhooks/<webhook-uuid>"Test
curl -X POST "$VOICEMATRIX_BASE_URL/webhooks/<webhook-uuid>/test" \
-H "X-API-Key: $VOICEMATRIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "event_type": "call.ended" }'Note the path: /webhooks/<id>/test, not /webhooks/test with an id in the body. And read ../webhooks.md#test-a-webhook before you rely on this for validation — it deliberately doesn't write a delivery-log row.
Pagination
Every list endpoint returns {"data": [...], "pagination": {"total", "limit", "offset", "has_more"}} — the same envelope everywhere.
curl -H "X-API-Key: $VOICEMATRIX_API_KEY" "$VOICEMATRIX_BASE_URL/calls?limit=20&offset=20"curl -s -H "X-API-Key: $VOICEMATRIX_API_KEY" "$VOICEMATRIX_BASE_URL/leads?limit=1" \
| jq '.pagination.total'Error handling
# $WRONG_KEY stands for anything that is not a live key.
curl -v -H "X-API-Key: $WRONG_KEY" "$VOICEMATRIX_BASE_URL/calls"Both failures are 401, but the code distinguishes a key that is the wrong shape from one that is well-formed and simply not on record — only the second is worth checking against your key list:
| What you sent | code |
|---|---|
Anything not shaped like vm_live_ + 32 characters | INVALID_API_KEY_FORMAT |
| Correctly shaped, but no matching key on record, or revoked | INVALID_API_KEY |
{ "error": { "code": "INVALID_API_KEY_FORMAT", "message": "Invalid API key format" } }Verified against a live deployment on 2026-08-25 — an earlier revision of this page showed a malformed key returning INVALID_API_KEY, which is not what the server answers.
Every error is a nested error object — code, message, and (for validation failures) fields. See ../errors.md for the full shape and known codes. This documentation does not claim specific X-RateLimit-* response headers exist — verify against a live response before depending on one; the authoritative rate-limit numbers are in ../authentication.md#rate-limits.
Useful jq one-liners
# Pretty-print
curl -H "X-API-Key: $VOICEMATRIX_API_KEY" "$VOICEMATRIX_BASE_URL/calls" | jq '.'
# Just the summary of one call
curl -s -H "X-API-Key: $VOICEMATRIX_API_KEY" "$VOICEMATRIX_BASE_URL/calls/<call-uuid>" | jq '.summary'Tips
-sfor silent mode,-ito see headers,-vfor verbose debugging.- Store the key in
.env, never commit it. - Always send
Idempotency-KeyonPOST /callsandPOST /agents/:id/phone-number— both cost real money on a retry. - Check response fields like
routing_liveandteardown_ok, not just the HTTP status — several endpoints on this API report a real-world outcome separately from whether the database write succeeded. See ../resources/phone-numbers.md and ../resources/call-control.md.