VoiceTele

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.