Developer hub
One key. The whole API surface.
A cm_ key opens chat, embeddings, speech, images, search, voice, WhatsApp, email and telephony. Nothing below needs a dashboard session — if you can paste a bearer token, you can call it.
curl -X POST https://api.callmissed.com/v1/chat/completions \
-H "Authorization: Bearer cm_your_api_key" \
-H "Content-Type: application/json" \
-d '{"model":"sarvam-105b","messages":[{"role":"user","content":"Hello in Hindi"}]}'That is the whole first request. Base URL, bearer key, a model id and a message.
Why build on CallMissed
- OpenAI-compatiblePoint the OpenAI SDK you already use at our base URL and change the key. The Anthropic SDK works too.
- Models on demandMany makers behind one key, each priced per token and published per model.
- Speech in 22 Indian languagesSpeech-to-text and text-to-speech on the same key, built for Hindi, Tamil, Bengali and the rest.
- Voice agentsA real-time voice session, or speech in and speech out over a single WebSocket.
Every account gets 1,000 free API credits on signup. Pricing · Text to speech · docs.callmissed.com
01 — Authenticate
Create a key in the console, then send it as a bearer token. Keys start with cm_, do not expire, and can be revoked at any time. Keep them server-side.
- Inference base URL
- https://api.callmissed.com/v1
- The OpenAI-compatible surface: chat, embeddings, audio, images, search, models.
- Resource base URL
- https://api.callmissed.com/api/v1
- WhatsApp, email, telephony, knowledge, bots, conversations, webhooks.
- Header
- Authorization: Bearer cm_…
- The /v1/messages endpoint also accepts x-api-key, so the Anthropic SDK works unchanged.
- Two kinds of grant
- permissions · scopes
- Service permissions (llm, stt, tts, search, image) gate the inference surface; resource scopes gate the /api/v1 surface.
02 — The endpoint map
16 families, one key. Each row is the primary call for that family; the reference behind it has the variants, the request schema and the model list.
16 families
- Chat and reasoning
POST /v1/chat/completionsOpenAI-compatible chat with streaming, tool calling and vision. - Anthropic-shaped chat
POST /v1/messagesThe same models through the Anthropic Messages shape. - Embeddings
POST /v1/embeddingsText to dense vectors for search and retrieval. - Speech to text
POST /v1/audio/transcriptionsTranscribe a file, with Indic code-mix output modes. - Text to speech
POST /v1/audio/speechSynthesize audio and get the bytes back in one response. - Image generation
POST /v1/images/generationsGenerate images through the OpenAI request shape. - Web search
POST /v1/searchLive web results, billed at a flat one credit a call. - Voice agent
POST /v1/voice/sessionsOpen a real-time voice session and get a connection token. - Managed voice agent
wss /v2/voice/agentSpeech in, speech out over a single WebSocket, no SDK. - WhatsApp
POST /api/v1/whatsapp/messagesSend text, media, template and interactive messages. - Email
POST /api/v1/email/sendTransactional mail from a domain you have verified. - Telephony
POST /api/v1/telephony/callsPlace an outbound call and read the call log back. - Knowledge
POST /api/v1/knowledge/searchSemantic search over sources you have ingested. - Usage
GET /v1/usage/summaryYour own spend and call counts, as JSON or CSV. - Webhooks
POST /api/v1/webhooksSubscribe to outbound events with a signed payload. - Model catalogue
GET /v1/modelsEvery model id you are allowed to call, with its rate.
Deep dives on the speech endpoints: speech to text · text to speech · Indian language coverage
03 — Build a request
Pick a chat model and the form only offers the reasoning_effort values the verified per-model matrix says it accepts — some models take the full ladder, some take only the off switch, and two drop the field entirely. The curl it writes is valid before you paste it.
"none" and "minimal" are mapped down to "low" — thinking cannot be switched off on this model.
curl -X POST https://api.callmissed.com/v1/chat/completions \
-H "Authorization: Bearer cm_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"model": "sarvam-105b",
"messages": [
{
"role": "user",
"content": "Hello in Hindi"
}
],
"stream": true
}'Using the OpenAI SDK? reasoning_effort goes in extra_body — the client rejects unknown kwargs. Raw HTTP sends it at the top level, as above.
The matrix this is built from: reasoning_effort by model
04 — SDKs
There is no separate client library to learn. Two SDK families work as-is: point the official OpenAI SDK at the inference base URL, or point the Anthropic SDK at the host and let it append its own version prefix. Go, PHP and Ruby OpenAI clients take the same override.
from openai import OpenAI
client = OpenAI(
api_key="cm_your_api_key",
base_url="https://api.callmissed.com/v1",
)
resp = client.chat.completions.create(
model="sarvam-105b",
messages=[{"role": "user", "content": "Hello in Hindi"}],
)import OpenAI from "openai";
const client = new OpenAI({
apiKey: "cm_your_api_key",
baseURL: "https://api.callmissed.com/v1",
});
const resp = await client.chat.completions.create({
model: "sarvam-105b",
messages: [{ role: "user", content: "Hello in Hindi" }],
});from anthropic import Anthropic
client = Anthropic(
api_key="cm_your_api_key",
base_url="https://api.callmissed.com",
)
msg = client.messages.create(
model="sarvam-105b",
max_tokens=512,
messages=[{"role": "user", "content": "Hello in Hindi"}],
)Note the difference: the OpenAI clients want the /v1 suffix on base_url, the Anthropic client does not — it adds one itself. SDK reference
05 — Limits and credits
One credit is ₹1 ≈ US$0.0104 (US$1 = ₹96). New accounts start with 1,000 credits, and each plan adds a monthly grant on top. Credits do not expire. Two separate things can stop a request, and they return different codes: run out of credits and you get 402, exceed the request rate and you get 429.
| Plan | Requests / minute | Monthly credits |
|---|---|---|
| free | 60 | 100 |
| starter | 500 | 550 first month, then 500 |
| pro | 3,000 | 6,000 first month, then 5,000 |
| enterprise | 10,000 | 26,000 first month, then 20,000 |
A per-key override set in the console wins over the plan default. Plan comparison
- X-RateLimit-Limit
- The ceiling this key is measured against.
- X-RateLimit-Remaining
- What is left in the current window.
- X-RateLimit-Reset
- When the window resets, as ISO-8601.
- X-Credits-Balance
- Credits left on the account after this call.
- X-Usage-Warning
- Set to warning at 80% of a cap, critical at 95%.
- Retry-After
- On a 429, how long to wait before trying again.
Headers on every response
06 — Errors
Failures come back in the standard OpenAI error envelope on the /v1 surface, so SDK error handling keeps working unchanged. Read the code field, not the message — messages are written for humans and can change.
{
"error": {
"code": "insufficient_credits",
"message": "Your credit balance is too low to complete this request.",
"type": "billing_error"
}
}Pick a status below for what causes it, the retry rule, and the named error codes published under it. 402 and 403 are never worth retrying; 429 tells you how long to wait.
200 — OK
Success.
Retry: Nothing to retry.
No named error codes are published for 200 — read the envelope's code field, not the message.
400 — Bad Request
Malformed JSON or an invalid parameter value.
Retry: Do not retry as-is — fix the body first.
No named error codes are published for 400 — read the envelope's code field, not the message.
401 — Unauthorized
Missing or invalid Authorization header, or an expired token.
Retry: Fix the credential, then retry.
- Documented error codes for 401
invalid_api_keyThe cm_ key is unknown or revoked.token_expiredJWT access token expired — refresh it.
402 — Payment Required
Insufficient credits or a monthly budget cap reached.
Retry: Do not retry — top up credits or raise the budget cap first.
- Documented error codes for 402
insufficient_creditsTop up credits to continue.budget_exceededMonthly credit budget cap reached.
403 — Forbidden
The key lacks the required scope or permission, or the domain is not allowlisted.
Retry: Do not retry — grant the permission or fix the allowlist first.
- Documented error codes for 403
permission_deniedThe key is missing the required service permission.search_provider_not_allowedThe key's allowed web-search providers exclude the requested provider.domain_not_allowedThe request origin is not in the key's domain allowlist.
404 — Not Found
The resource ID does not exist, or belongs to another tenant.
Retry: Do not retry — check the id.
- Documented error codes for 404
not_foundThe resource does not exist in your tenant.
409 — Conflict
A duplicate resource, or an Idempotency-Key replayed with a different body.
Retry: Do not retry as-is — this is how a reused key tells you the body changed.
No named error codes are published for 409 — read the envelope's code field, not the message.
422 — Unprocessable Entity
Schema validation failed — a bad enum or an out-of-range number.
Retry: Fix the field named in the response, then retry.
No named error codes are published for 422 — read the envelope's code field, not the message.
429 — Too Many Requests
Rate limit exceeded.
Retry: Honour the Retry-After header (seconds), then back off exponentially.
- Documented error codes for 429
rate_limit_exceededSlow down — see Retry-After.
500 — Internal Server Error
An unexpected error on our side.
Retry: Safe to retry once or twice with jittered backoff. Send an Idempotency-Key on mutating calls first.
No named error codes are published for 500 — read the envelope's code field, not the message.
501 — Not Implemented
The endpoint exists but the feature is not yet live.
Retry: Do not retry — the feature is not available.
No named error codes are published for 501 — read the envelope's code field, not the message.
503 — Service Unavailable
An upstream provider is temporarily unavailable.
Retry: Retry once or twice with jittered backoff.
- Documented error codes for 503
provider_errorThe upstream model or provider failed.
07 — Idempotency
Send an Idempotency-Key on any POST, PUT or PATCH and a retry after a dropped connection replays the original response instead of doing the work twice. Reuse the key with a different body and the call is rejected with 409, which is how you find a bug rather than double-charge someone. Keys are scoped to your account.
curl -X POST https://api.callmissed.com/api/v1/bots \
-H "Authorization: Bearer cm_your_api_key" \
-H "Idempotency-Key: 6f1c2b7e-9a41-4d0e-9a1e-1f2b3c4d5e6f" \
-H "Content-Type: application/json" \
-d '{"name": "Support bot"}'08 — Agent tools over MCP
The same account is reachable as an MCP server over streamable HTTP, so a coding agent or assistant can place a call, read a transcript, search the CRM or send a message without you writing a client. Connect with the same cm_ key, or sign in with OAuth and approve the tool groups you want to expose.
claude mcp add --transport http callmissed \
https://api.callmissed.com/api/v1/mcp \
--header "Authorization: Bearer cm_your_api_key"A second, credential-free MCP server serves the documentation itself, so your agent can read the reference while it writes the integration. MCP reference




