v2.3 · 16 OCT 2026
One API. A direct line to your clients.
Make calls, follow call activity and retrieve recordings through a token-authenticated HTTPS API. No private-network connection is required for your CRM backend.
https://voice-api.tychedevs.com/api/v101 Get connected
Your administrator sets your organization, enabled features, token scopes and expiry. Keep it in your CRM backend’s secret store. Never embed it in frontend code or URLs.
export VOICE_API_TOKEN='YOUR_TOKEN' curl --fail-with-body \ 'https://voice-api.tychedevs.com/api/v1/status' \ -H "Authorization: Bearer $VOICE_API_TOKEN"
Expect 200. Check ami_connected, outbound_enabled and recording_storage_available. Calling must be enabled by the administrator.
02 Place a test call
curl --fail-with-body -X POST \
'https://voice-api.tychedevs.com/api/v1/calls' \
-H "Authorization: Bearer $VOICE_API_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: crm-test-001' \
--data '{"agent_extension":"115",
"destination":"09171234567",
"number_type":"ph_mobile",
"client_id":"crm-client-123"}'import { randomUUID } from 'node:crypto';
const key = randomUUID(); // Persist; reuse on retries.
const res = await fetch(
'https://voice-api.tychedevs.com/api/v1/calls', {
method: 'POST', headers: {
Authorization: `Bearer ${process.env.VOICE_API_TOKEN}`,
'Content-Type': 'application/json',
'Idempotency-Key': key
}, body: JSON.stringify({ agent_extension: '115',
destination: '09171234567', number_type: 'ph_mobile' })
});
const result = await res.json();
if (!res.ok) throw new Error(result.error?.message);
console.log(result.id, result.status);client_id is an optional CRM reference. A 202 response contains the call id; it means accepted, not answered. Use a new idempotency key for each intended call. Reuse the same key only when retrying the same payload. Never automatically redial an unknown outcome.
03 Add the call button to your CRM
Your UI sends the selected client and number to your CRM backend. Your backend checks the CRM user’s permissions, calls POST /calls and returns the call ID. Poll GET /calls/{id} to update the UI. Centralize polling; incoming calls can be observed with GET /calls?direction=inbound.
Typical states: queued → agent_ringing → dialing → ringing → answered → completed. Busy, no_answer, failed and unknown are also possible; not every intermediate state is observed.
04 Choose the number format
| Destination | number_type | Input example |
|---|---|---|
| Philippine mobile | ph_mobile | 09171234567or +639171234567 |
| Philippine landline | ph_landline | 0281234567Include 0 + area code |
| International | international | +442079460123+ country code + number |
Send the number as a string, without spaces or route prefixes. The telephony system uses its existing routing and carrier permissions.
05 The endpoints you need
| Method / path, relative to base URL | Purpose |
|---|---|
| GET/status | Connection and service readiness |
| POST/calls | Create an agent-first call |
| GET/calls | Call activity; direction / updated_since |
| GET/calls/{id} | Current status of a tracked call |
| GET/calls/{id}/recordings | Confirmed recordings + match status |
| GET/recordings | Search date, number, extension, direction |
| GET/recordings/{id} | Audio availability and metadata |
| GET/recordings/{id}/audio | WAV playback; byte ranges supported |
Client tokens are organization-scoped and restricted by enabled features and assigned resources. Tokens expire; revoked or expired tokens return 401.
06 Find and play recordings
- Search
/recordings?date=2026-10-15&limit=50. Dates use Manila time. Follownext_cursoruntil null. - When
status=available, use the returnedaudio_urlwith bearer authentication. Add?download=trueto download. - For browser playback, stream through an authenticated CRM backend route and forward the
Rangeheader. A partial response returns206.
New audio may take several minutes. Completeness is unverified. Call-to-recording candidates require operator confirmation; don’t treat an empty pending list as a failure.
07 Handle responses clearly
Application limit: 240 requests/minute per token. Additional per-IP and concurrency limits apply. Keep credentials on the server; direct browser CORS integration is not enabled.