Developers · Odile Direct
Odile Direct: the business line AI agents book direct
An automated assistant can find an opted-in business, read its public agent card and send a structured message or booking request. Paying customer lines are off until the business opts in. Demo lines are on.
Pricing for AI agents
| Caller | Lookups | Tasks |
|---|---|---|
| No key | Free, 30/IP/hour | Free, 30/IP/hour |
| Developer key | Free, 10,000/key/day | First 50 completed tasks per account per calendar month free. Then: message 1 credit, availability 0, confirmed booking 5 credits. |
Direct 100: 100 credits for $10.00. Credits never expire; nothing renews. Failed, rejected and input-required tasks cost nothing. At zero credits, paid tasks are rejected before delivery. Phone minutes are separate. Name your app and buy credits. Agent storefront: buy without signup.
Send Authorization: Bearer <developer API key> to use your account. GET /a2a/v1/usage shows this month's allowance, balance and last 20 charges; POST /a2a/v1/credits/checkout returns the Stripe checkout URL. Authenticated MCP shares the allowance and credits. Repeat the same messageId (MCP: message_id) and task data on retries; a reused ID with changed data is rejected. One keyed task runs per account at a time; a 409 asks you to retry. An interrupted task holds the account until its outcome is reconciled. Calendar months and lookup days use America/New_York.
Not an Odile customer?
Claim your number free. AI assistants can leave a message by email. Free listings offer take_message only, up to 20 messages per day, and may not reply quickly. SMS verification is required; landlines cannot be verified yet.
1. Resolve a number
curl 'https://api.odilelabs.com/a2a/v1/resolve?number=%2B15615295370'
2. Read the agent card
curl 'https://api.odilelabs.com/a2a/v1/b/demo-club/agent-card.json'
3. Send a task
curl 'https://api.odilelabs.com/a2a/v1/b/demo-club' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"SendMessage","params":{"message":{"messageId":"11111111-1111-4111-8111-111111111111","role":"ROLE_USER","parts":[{"data":{"skill":"take_message","caller_name":"Example Caller","callback_number":"+12025550123","need":"Please call me about a repair"},"mediaType":"application/json"}]}}}'
The demo business is fictional. Messages use its demonstration inbox. Only cards advertising calendar skills can book (this club demo takes messages only). For a calendar-enabled business, send {"skill":"check_availability","service":"Repair","date":"2026-10-20"} (service and date are optional). Use the returned slots[].slot unchanged in {"skill":"book","slot":"SIGNED_SLOT","caller_name":"Example Caller","callback_number":"+12025550123","need":"Repair"}. Ask the customer for permission before booking.
Already on a call?
Our phone assistant can issue a single-use 6-digit code. Read this page, use the business endpoint returned by resolve, and include "handshake_code":"481273" in the skill data. The code lasts 10 minutes, works for that business only and links the request to that call. The page does not redeem a code; your assistant sends it with the task.
Limits and fields
Without a key, resolve/cards and tasks each allow 30 requests per IP per hour. Keyed requests use the per-key lookup cap above and bypass IP caps; a valid call code also bypasses task IP limits. Booking keeps the web form’s 5 attempts per IP per hour for unkeyed requests, 30 per business per local day and 2 per callback number per local day for everyone. Verified listings keep their 20 messages per day cap for everyone. KV IP and business counters are approximate under concurrent load. Signed slots last one hour and are rechecked before booking. Bodies are limited to 8 KB.
Names and on_behalf_of: 100 characters. Need: 500. Service: 120. Callback numbers must be E.164. For take_message, urgency may be low, normal, high, urgent or a boolean; on_behalf_of is optional. Dates use YYYY-MM-DD. A2A v1.0 responses wrap the Task in result.task, with TASK_STATE_COMPLETED, TASK_STATE_FAILED, TASK_STATE_INPUT_REQUIRED or TASK_STATE_REJECTED status. Missing fields appear in the status message. Legacy message/send, user role and kind: data parts are accepted; all replies use v1.0. Only SendMessage is supported; other methods return -32601. Requests may use application/json or application/a2a+json; replies use application/json. MCP exposes find_business_agent and send_to_business with the same limits.
The directory card is at /.well-known/agent-card.json. Its JSON-RPC interface at https://api.odilelabs.com/a2a/v1 accepts {"skill":"find_business_agent","number":"+15615295370"} as the data part, using the same lookup and allowance as resolve.
AI callers must still say they are automated. Only public name, trade, town, hours and services appear in the agent card.