{"version":1,"resources":["https://stablephone.dev/api/call","https://stablephone.dev/api/call/:id","https://stablephone.dev/api/numbers","https://stablephone.dev/api/number","https://stablephone.dev/api/number/topup","https://stablephone.dev/api/lookup","https://stablephone.dev/api/lookup/status"],"mppResources":["https://stablephone.dev/api/call","https://stablephone.dev/api/number","https://stablephone.dev/api/number/topup","https://stablephone.dev/api/lookup"],"description":"Pay-per-call AI phone calls. No API keys, no accounts.","instructions":"# StablePhone API\n\nAI phone calls and phone numbers via micropayments. USDC on Base. No API keys.\n\n## Make a call\n\nPOST /api/call ($0.54)\n\nBody (JSON):\n{\n  \"phone_number\": \"+14155551234\",\n  \"task\": \"Call this person and ask if they're available for a meeting tomorrow at 2pm.\"\n}\n\nRequired fields:\n- phone_number: E.164 format (e.g. +14155551234)\n- task: Instructions for the AI agent (what to say, how to behave)\n\nOptional fields:\n- from: Outbound caller ID — must be an active StablePhone number (see POST /api/number)\n- first_sentence: Specific opening line\n- voice: Voice preset (see below) or any Bland.ai voice ID\n- max_duration: Max call length in minutes (1-30, default 5)\n- wait_for_greeting: Wait for recipient to speak first (default false)\n- record: Record call audio (default true)\n- model: \"base\" (default, best for most cases) or \"turbo\" (lowest latency)\n- transfer_phone_number: Number to transfer to if caller requests a human\n- voicemail_action: \"hangup\" (default), \"leave_message\", or \"ignore\" (bypasses detection — best for leaving voicemails naturally)\n- voicemail_message: Message to leave on voicemail (required when voicemail_action is \"leave_message\")\n- metadata: Custom key-value data to attach to the call\n\nResponse: { \"success\": true, \"call_id\": \"abc-123-def\", \"message\": \"Call initiated\" }\n\n## Check call status\n\nGET /api/call/{call_id} (SIWX, free) — only the wallet that initiated the call can poll.\n\nResponse includes: status, completed, to, from, call_length, answered_by, summary, transcript, transcripts (array), recording_url, price, error_message, created_at.\n\n## Buy a phone number\n\nPOST /api/number ($20.00)\n\nBody (JSON):\n{\n  \"area_code\": \"415\",\n  \"country_code\": \"US\"\n}\n\nOptional fields:\n- area_code: 3-digit US/CA area code (random if omitted)\n- country_code: \"US\" (default) or \"CA\"\n\nResponse: { \"success\": true, \"phone_number\": \"+14155551234\", \"expires_at\": \"2025-07-14T...\" }\n\nNumbers expire after 30 days. Top up to extend.\n\n## Top up a phone number\n\nPOST /api/number/topup ($15.00)\n\nBody (JSON):\n{\n  \"phone_number\": \"+14155551234\"\n}\n\nExtends the number by 30 days from the current expiry (or from today if already expired). Top-ups stack — call it multiple times to prepay months ahead. Anyone can top up any number.\n\nResponse: { \"success\": true, \"phone_number\": \"+14155551234\", \"expires_at\": \"2025-08-14T...\" }\n\n## List your numbers\n\nGET /api/numbers (SIWX, free) — returns numbers for the authenticated wallet. No query params.\n\nResponse: { \"success\": true, \"numbers\": [{ \"phone_number\": \"+14155551234\", \"expires_at\": \"...\", \"area_code\": \"415\", \"country_code\": \"US\" }] }\n\n## Typical flow\n1. POST /api/call → get 402 Payment Required\n2. Pay with x402-compatible client (USDC on Base)\n3. Receive call_id\n4. Poll GET /api/call/{call_id} until completed=true\n5. Read transcript and summary\n\n## Phone number flow\n1. POST /api/number → buy a number ($20.00, active 30 days)\n2. Use \"from\" field in POST /api/call to call from your number\n3. POST /api/number/topup → extend by 30 days ($15.00)\n4. GET /api/numbers (SIWX) → list your active numbers\n\n## iMessage/FaceTime lookup\n\nPOST /api/lookup ($0.05)\n\nBody (JSON):\n{\n  \"phone_number\": \"+14155551234\"\n}\n\nRequired fields:\n- phone_number: E.164 format (e.g. +14155551234)\n\nResponse (202): { \"token\": \"<jwt>\" }\n\nThe lookup is async (30-90 seconds typical). Use the token to poll for results:\n\nGET /api/lookup/status?token=<jwt> (SIWX, free) — only the wallet that paid can poll.\n\nPoll responses:\n- { \"status\": \"pending\", \"message\": \"...\" } — still processing, poll again in a few seconds\n- { \"status\": \"complete\", \"phone_number\": \"+1...\", \"imessage\": \"available\"|\"unavailable\"|\"unknown\", \"facetime\": \"available\"|\"unavailable\"|\"unknown\"|\"pending\", \"carrier\": {\"carrier\": \"...\", \"number_type\": \"...\"}, \"country\": {\"name\": \"...\", \"iso2\": \"...\", \"flag\": \"...\"}, \"checked_at\": \"2026-02-20\" }\n- { \"status\": \"error\", \"error\": \"...\" } — upstream error\n\nNotes:\n- \"unknown\" means the number exists but iMessage/FaceTime status can't be determined (likely landline/VoIP)\n- Token expires after 60 minutes. If expired, submit a new lookup (re-pay)\n- Same number submitted within ~1 hour reuses the cached result (no extra charge)\n\n## Lookup flow\n1. POST /api/lookup with phone_number → get 402 Payment Required\n2. Pay with x402-compatible client (USDC on Base)\n3. Receive { token } (202)\n4. Poll GET /api/lookup/status?token=<jwt> every 3-5 seconds\n5. When status is \"complete\", read imessage/facetime fields\n\n## Voices\n- nat (default): American female\n- josh: Articulate American male\n- maya: Young American female, soft\n- june: American female\n- paige: Calm, soft-tone female\n- derek: Soft and engaging male\n- florian: German male\n\n## Authentication\n- **Paid endpoints** (call, number, number/topup, lookup): x402 payment (USDC on Base).\n- **Free endpoints** (call status, numbers, lookup status): SIWX required. Use fetch_with_auth / authed_call. Only the owning wallet can access their data.\n\n## Discovery\n- GET /.well-known/x402 — machine-readable resource discovery\n- GET /llms.txt — this file"}