API reference
Base URL: https://voicetele.com/api. All requests and responses are JSON. Everything you can do in the portal is available here under the same account.
Authentication
Create a key in API keys (portal) and send it as a bearer token:
curl https://voicetele.com/api/me \
-H "Authorization: Bearer vt_sandbox_3Kx…"
Keys are shown once and stored hashed. vt_sandbox_… and vt_live_… keys currently act on the same account and balance; use the sandbox key in development so it can be revoked without touching production integrations. Revoke a key any time with DELETE /keys/{id} or from the portal.
Portal sessions (cookie vt_session) work for the same endpoints from a browser.
Errors
Non-2xx responses carry { "error": "human readable message" }.
| Status | Meaning |
|---|---|
| 400 | Validation failed, the message says which field |
| 401 | No or invalid key / session |
| 402 | Insufficient balance |
| 403 | Not allowed (wrong password, unverified email, bad ingest key) |
| 404 | Object not found on this account |
| 409 | Conflict (email already registered) |
| 429 | Rate limited, retry after the window in the message |
| 500 | Our side; retry with backoff |
Default limit: 600 requests per minute per key.
Account
GET /me → { user: { id, email, name, company, verified, balance_cents, level, created_at } }
PATCH /me { name?, company? }
POST /me/password { current, password }
GET /me/sessions → active portal sessions.
Catalogue (no auth required)
GET /catalog/rates?q=cyprus → { rates: [ { prefix, name, standard_mc, premium_mc } ] }. Rates are in 1/10 000 USD per minute (95 = $0.0095/min).
GET /catalog/numbers → countries and ranges. GET /catalog/numbers?country=CY adds numbers[] (live inventory) to each range, each with a sku to buy.
Numbers
GET /numbers → { numbers: [ { id, e164, country, city, type, monthly_cents, route_type, route_target, status, renews_at } ] }. status is active, pending_kyc or released.
POST /numbers { sku, route_type?, route_target? }, buys the number; first month (+ setup) is charged. Returns { id, status }.
curl -X POST https://voicetele.com/api/numbers \
-H "Authorization: Bearer $KEY" -H "content-type: application/json" \
-d '{"sku":"+357245551000","route_type":"trunk","route_target":"trk_9a1…"}'
PATCH /numbers/{id} { route_type: "trunk" | "sip" | "pstn", route_target }, route_target is a trunk id, a SIP URI or an E.164 number.
DELETE /numbers/{id}, releases the number.
SIP trunks
GET /trunks → { trunks: [ … ], pops: [ "lon-1", … ] }. Each trunk carries username, password, pop, auth (registration | ip), ip_allow, channels, route_class, status.
POST /trunks { name, pop, auth?, ip_allow?, channels?, route_class? } → { id }. Credentials are generated; read them with GET /trunks.
PATCH /trunks/{id}, any of the fields above plus status: "active" | "paused".
DELETE /trunks/{id}
Calls
POST /calls/test { trunk_id, to }, places a short test call through the trunk and writes a call record. Returns { result, duration, cost_cents, rate }.
GET /cdrs?from=<ms>&to=<ms>&direction=inbound|outbound → up to 500 most recent records: { cdrs: [ { id, direction, from_num, to_num, trunk_id, started_at, duration, result, cost_cents } ] }. Defaults to the last 30 days. Timestamps are Unix milliseconds.
# yesterday's outbound calls
curl "https://voicetele.com/api/cdrs?from=$(( $(date +%s)*1000 - 86400000 ))&direction=outbound" \
-H "Authorization: Bearer $KEY"
Billing
GET /billing → { balance_cents, level, spent_30d_cents, transactions: [ { id, kind, amount_cents, description, created_at } ] }. kind is credit, topup, number, call, refund or pending.
POST /billing/topup { amount_cents, method }, records a top-up request; the payment step follows in the portal.
API keys
GET /keys → { keys: [ { id, label, env, key_prefix, created_at, last_used_at } ] }
POST /keys { label, env: "sandbox" | "live" } → { id, key }, the only time the full key is returned.
DELETE /keys/{id}, revokes immediately.
Webhooks
Call events (call.started, call.answered, call.ended, recording.ready, balance.low) pushed to your URL with a signed payload are on the roadmap; until then poll GET /cdrs and GET /billing. Tell [email protected] if you need them sooner, it moves the priority.
SDKs
Official Python, Node, PHP and Go packages are in preparation. The API is plain REST with bearer auth, so any HTTP client works today.