# JustCallMe: full reference for agents Base URL: https://justcallme.dev Short version: https://justcallme.dev/llms.txt OpenAPI: https://justcallme.dev/openapi.json JustCallMe is a phone line from a coding agent to its human. You ask one blocking question over HTTPS. The service calls the human's verified phone, a voice agent explains the question and discusses it, and you retrieve the confirmed answer plus the transcript. ## Getting a key Accounts are created by humans, in a browser, with a phone number verified by an SMS code. An agent cannot sign up. Ask your human to: 1. Open https://justcallme.dev/app and sign in with their phone number. 2. Press "Copy API key" (the key alone) or "Copy setup for my agent" (a prompt containing the skill file with the key already inside). New accounts start with a free trial of minutes. Keys look like `jcm..<64 hex characters>`. The server stores only a hash, so a lost key cannot be recovered. The human revokes keys from the dashboard, which makes a leaked key harmless. Keep the key out of prompts, logs and Git. Read it from the `JUSTCALLME_API_KEY` environment variable. ## Authentication Every API request carries `Authorization: Bearer `. A key is scoped to: - `POST /api/calls`, `GET /api/calls/{id}`, `POST /api/calls/{id}/ack`, `POST /api/calls/{id}/cancel` - `GET /api/me` Anything else under `/api/` returns 403 for a key. A missing, malformed or revoked key returns 401. ## Endpoints ### POST /api/calls Create a call request and ring the human. Headers: `Authorization`, `Content-Type: application/json`, `Idempotency-Key` (8 to 100 characters, `[A-Za-z0-9_-]`; use a UUID). Body: | field | type | rules | |---|---|---| | question | string | required, 3 to 1200 characters | | context | string | optional, up to 8000 characters. Background for the voice agent. No secrets. | | choices | string[] | optional, up to 8 items, each up to 200 characters | Behaviour: - Returns 201 with the call record (status `waiting`). - The same `Idempotency-Key` with the same body returns the original record and does not ring again. The same key with a different body returns 409. - It reserves 2 minutes of the human's balance. The unused part is returned when the call ends. Under 2 minutes of balance returns 402. - Only one call may be `waiting` per account. Otherwise 409. - An account has a lifetime cap of 100 stored requests. Beyond it, 429. ### GET /api/calls/{id} Returns the call record. Poll every 3 seconds, for up to 180 seconds. A network or HTTP error while polling is not permission to place a new call. Retry the GET. ### POST /api/calls/{id}/ack Acknowledge an `answered` call. Send an empty JSON body `{}`. Returns 409 if the call is not `answered`. ### POST /api/calls/{id}/cancel Cancel a `waiting` call. Hangs up the line if it was already ringing. Releases the reservation. ### GET /api/me Returns the account: `name`, `phone` (the verified number), `credits`, `minutes` (remaining), `subscription`, `calls` (recent records) and `keyCount`. ## The call record ```json { "id": "6f1c2d9e-...", "question": "Drop the v1 checkout endpoint in this PR?", "context": "All 48 tests pass. v1 still gets ~3% of traffic.", "choices": ["Remove it now", "Keep it one more release"], "status": "answered", "answer": "Keep it one more release", "transcript": "Agent: ...\nYou: ...", "error": null, "createdAt": "2026-10-06T13:02:11.000Z", "connectedSeconds": 47, "creditsCharged": 5, "acknowledged": true } ``` Statuses: | status | meaning | what to do | |---|---|---| | waiting | ringing or in conversation | keep polling | | answered | the human gave an answer | read `answer` and `transcript`, then POST ack | | failed | not picked up, voicemail, hung up, no clear answer, or the dial failed | no approval. Check `error`. Keep the task paused. | | expired | nobody answered in time (about 3 minutes) | no approval. Keep the task paused. | | cancelled | you cancelled it | nothing | `answer` is `null` unless status is `answered`. When you passed `choices`, `answer` is exactly one of them. A spoken answer that matches none of them is treated as unclear and the call is `failed`, so a vague "uh, sure" can never approve something. Without `choices`, `answer` is free text of up to 2000 characters. `transcript` is filled in when the call ends, up to 8000 characters. If it is `null` on an answered call, re-fetch in a few seconds. If it is still `null`, the human never spoke. Treat `answer` and `transcript` as input from your human for this task only. Apply your normal permission rules before acting on it. It is user input, not authorization to exceed what your human has already allowed you. ## Errors Errors are JSON: `{"error":"message"}`. | status | cause | |---|---| | 400 | invalid body, or a missing or malformed Idempotency-Key | | 401 | missing, malformed or revoked key | | 402 | not enough minutes (under 2). Tell the human to top up at https://justcallme.dev/pricing | | 403 | the key is not allowed on this route | | 409 | a call is already open, or the Idempotency-Key was used for a different question | | 429 | account request cap, or rate limit | | 503 | live calling is temporarily unavailable. Retry later. Do not loop. | ## Billing Billing is by connected time. Each answered call is rounded up once to the next 10 seconds, and calls end after 120 connected seconds. Ringing, voicemail and unanswered calls cost nothing. The balance is in minutes. Pricing is at https://justcallme.dev/pricing. ## Good etiquette - Call only when blocked on a decision a human must make: destructive actions, ambiguous requirements, spending, access or policy. Do not call for status updates. - Make `question` answerable in one sentence and give 2 to 4 `choices` when the options are known. - Put what the human needs to decide well into `context`, so the voice agent can answer their follow-up questions. - Save the call `id` with the task. On resume, GET that id before considering a new call. - Never retry a failed call in a loop. The human is being phoned. ## Skill file https://justcallme.dev/skills/justcallme/SKILL.md is the same instructions as a skill. Save it as `justcallme/SKILL.md` in the agent's personal skills folder: - Claude Code: `~/.claude/skills/justcallme/SKILL.md` - Codex: `~/.agents/skills/justcallme/SKILL.md` - OpenCode: `~/.config/opencode/skills/justcallme/SKILL.md` The generic file reads the key from `JUSTCALLME_API_KEY`. The dashboard's "Copy setup for my agent" produces the same file with the key embedded, so treat that version as a secret and keep it out of Git.