What Vocaleo is
Vocaleo lets a personal AI assistant place one phone call and read one structured result. You hand over a phone number and a task in plain language; Vocaleo makes the call and returns what happened as machine-readable facts, not a transcript to parse. The customer is the agent. This page is written for you, the agent.
Machine-readable index
- OpenAPI 3.1: /openapi.json
- Agent index: /llms.txt
The whole API is four calls
1. Create an account
POST /v1/accounts, no authentication. The response carries the API key — shown once, never again, because Vocaleo stores only its hash — and a payment_url.
curl -s -X POST https://api.vocaleo.co/v1/accounts
# response
{
"account_id": "acct_...",
"api_key": "vok_...", # shown once — save it now
"balance_cents": 0,
"payment_url": "https://buy.stripe.com/...",
"price_cents_per_minute": 50,
"max_charge_cents_per_call": 500
}2. Fund it
Send your user to the payment_url to add credit; a human with a card does this once. If payment_url is null, Stripe is not connected to that environment yet. Check the balance any time with the API key:
curl -s https://api.vocaleo.co/v1/account \
-H "Authorization: Bearer $VOCALEO_API_KEY"A call is admitted only when the balance covers max_charge_cents_per_call, which is held for the call and mostly refunded when it settles.
3. Place the call
POST /v1/calls. Write the task the way you would brief a person: what to accomplish, and what to accept if the first answer is no. Send an optional Idempotency-Key header to make retries safe.
curl -s -X POST https://api.vocaleo.co/v1/calls \
-H "Authorization: Bearer $VOCALEO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to_phone_number": "+14155550123",
"task": "Call Lume and book a table for 2 tomorrow at 7pm under Alex Rivera. Accept 6:30-8:00 as fallback.",
"on_behalf_of": "Alex Rivera"
}'
# response 202
{ "call_id": "call_...", "status": "queued", "held_cents": 500 }4. Read the result
GET /v1/calls/{call_id}. wait_seconds (0 to 60) holds the request open until the call reaches completed or error. A call usually outlives one wait, so repeat until the status is one of those two.
curl -s "https://api.vocaleo.co/v1/calls/$CALL_ID?wait_seconds=60" \
-H "Authorization: Bearer $VOCALEO_API_KEY"
# response once terminal
{
"call_id": "call_...",
"status": "completed",
"outcome": "achieved",
"summary": "Booked a table for 2 at Lume tomorrow at 7:00pm under Alex Rivera.",
"transcript": [
{ "role": "assistant", "content": "Hi, this is an AI assistant calling on a recorded line for Alex Rivera..." },
{ "role": "user", "content": "Sure, 7pm for two, what name?" }
],
"failure": null,
"held_cents": 500,
"charged_cents": 150,
"balance_cents": 850
}What a call promises
The agent says it is an AI on a recorded line, names the person it calls for when you set on_behalf_of, and never invents a fact you did not give it. Vocaleo calls US and Canada numbers only, and a task screen refuses harassment, fraud, impersonation of a real person, emergency-service calls, and unsolicited marketing.
The result
outcomeis one of: achieved, partial, not_achieved, unclear.transcriptis a list of{"role": "assistant" | "user", "content": "..."}.- On
error,failure.codeis one of: no_answer, busy, error. - While a call is not terminal,
outcome,summary,transcript, andcharged_centsarenull.
Authentication
Every authenticated request carries the API key as a bearer token: Authorization: Bearer vok_.... The key is shown once at account creation. Store it securely; never send it over a chat channel.
Price
Read the price from the account response — price_cents_per_minute and max_charge_cents_per_call. These are the source of truth; do not hardcode a number. A call holds the maximum up front and refunds the difference when it settles. A call that errors is not charged, and the whole hold is returned.
Errors
Every error body is {"error": {"code", "message"}} plus any named extra fields. Codes: unauthorized, not_found, invalid_request, task_rejected, insufficient_credit, rate_limited, conflict, temporarily_unavailable, executor_error.
402 insufficient_credit— the balance does not cover one call.needed_centsandpayment_urlare in the body.422 task_rejected— the task screen refused it; the message says why.429 rate_limited— a cap was hit;Retry-Aftersays how long.503 temporarily_unavailable— new calls are switched off, or the voice pipeline is at capacity. Nothing was spent.
Endpoint summary
POST /v1/accounts(none) — Create an account. Returns the API key once, plus a payment link.GET /v1/account(bearer) — Read the balance and payment link.POST /v1/calls(bearer) — Start one call: a phone number and a task.GET /v1/calls/{call_id}(bearer) — Read status and, when done, the result. wait_seconds holds the request open.