ciro.chat

Your customer is yours. The conversation should be too.

A public API on the WhatsApp Web protocol. Your number, your device, your terms — no provider to apply to, no template review, and no fee on every sentence you send.

Free tier · bring your own numberNo cardFirst message in minutes

You need the right to use every number you connect, and you are responsible for complying with the terms of the networks you reach. Ciro is for conversations with people who chose you — accounts that reach strangers get closed. Acceptable use

Who it's for

Three ways in. One API.

The same endpoints serve a developer wiring up an internal tool, a platform provisioning thousands of customers, and an AI agent that needs a number of its own.

01 — you are building one product

Put messaging inside your own product.

Create a channel, drop the pairing widget into your app, and your user connects by scanning a code with their own phone. The session runs in our cloud.

You host nothing. No container to keep alive, no session files to back up, no pairing screen to design.

Create a channelPOST /v1/channels
# BYOD — your number, your device
curl -X POST https://api.ciro.chat/v1/channels \
  -H "x-api-key: $CIRO_KEY" \
  -d '{"name":"Support","deviceModel":"byod"}'
Pair itPOST /v1/widget/sessions
# mint a short-lived session, then embed
curl -X POST https://api.ciro.chat/v1/widget/sessions \
  -H "x-api-key: $CIRO_KEY" \
  -d '{"channelId":"'$ID'"}'

<iframe src="https://ciro.chat/embed?token=SESSION_TOKEN"
        allow="camera" width="380" height="440"></iframe>
SendPOST /v1/channels/:id/messages
curl -X POST https://api.ciro.chat/v1/channels/$ID/messages \
  -H "x-api-key: $CIRO_KEY" \
  -d '{"contact":"5511999998888","body":"Your order shipped."}'
02 — your customers have customers

Provision a thousand tenants by API.

One authenticated call creates the organisation, the company, the API key and the first admin user — atomically. Then embed the white-label widget and each of your customers connects their own numbers, as many as they need.

Tenancy is ours. The relationship stays yours. Isolation is enforced in the database, two levels deep, not in your application code.

Provision a tenantPOST /partner/tenants
curl -X POST https://api.ciro.chat/partner/tenants \
  -H "x-partner-token: $CIRO_PARTNER_TOKEN" \
  -d '{
        "organizationName": "Acme Retail",
        "companyName": "Acme HQ",
        "adminEmail": "[email protected]"
      }'

# 201 →
#   organizationId · companyId · apiKey
#   admin: { email, tempPassword }
Then, in your productyour product
# your colours, your domain
<iframe src="https://ciro.chat/embed?token=…&accent=%23C1552F"></iframe>

# the number goes live
window.addEventListener("message", (e) => {
  if (e.data.type === "ciro:connected") activate(e.data.channelId);
});
03 — your agent needs a number

Give your agent a WhatsApp number.

An MCP server, so Claude Code and any agent that speaks the protocol can read and send messages on a number you own. One command to install, no backend of your own, and every tool maps to an endpoint that already exists.

“Tell the client the deploy is done.” — and it arrives, from your number, in the thread they already know.

InstallMCP
claude mcp add ciro -- npx -y @ciro/mcp
# CIRO_API_KEY=…
What the agent gets8 tools
ciro_list_channels     → GET  /v1/channels
ciro_create_channel    → POST /v1/channels
ciro_connect_channel   → POST /v1/channels/:id/start
ciro_channel_status    → GET  /v1/channels/:id
ciro_send_message      → POST /v1/channels/:id/messages
ciro_read_messages     → GET  /v1/channels/:id/messages
ciro_channel_events    → GET  /v1/channels/:id/events
ciro_set_webhook       → POST /v1/webhooks

Why now

They said the conversation would be free.

Build on us, they said. Bring your customers here. So an industry did — a decade of support threads, order updates, delivery notices, appointment reminders, all moved onto one network. Then the gate closed. Now every sentence you send to the people who already chose you carries a fee.

We are not here to ask for a smaller fee.

What's different

Built like infrastructure, not like a weekend project.

You host nothing

The session runs in our cloud. You bring a number and a device to pair it once — that is the entire operational burden. Self-hosted kits hand you a container and wish you luck at 3am.

Multi-tenant, natively

Organisation → Company → Channel, isolated at the database with row-level security, two levels deep. Keys are scoped per company. Nothing else in this category ships tenancy — you would be building it yourself, and getting it wrong once is a data breach.

Provisioning is one call

A single authenticated request creates a tenant, a company, an API key and an admin user, atomically. Reselling is a primitive here, not a spreadsheet and a support ticket.

A pairing widget you embed

A short-lived per-channel token, an allowed origin, your accent colour, and a message to your page the moment the number goes live. Fifteen minutes of integration instead of a week of polling logic.

Webhooks that don't drop

Signed with HMAC-SHA256, queued through an outbox, retried with backoff, and parked in a dead-letter queue you can read. One delivery in flight per channel and parallel across channels — a noisy customer cannot stall a quiet one.

State you can watch

Status changes stream the moment they happen, and every transition lands in an append-only event log. Nothing about a channel is a mystery you have to reconstruct from logs.

Where it sits

Three honest columns.

Ciro Self-hosted toolkitOfficial API
Who runs the infrastructure We do You do The platform
Multi-tenant Native, two levels You build it Per account
Fee per message None None Yes
Template approval None None Required
Pairing UI Embeddable widget You build it Hosted flow
Provisioning API Yes, atomic You build it Partner programme
Delivery guarantees Outbox, HMAC, DLQ Usually fire-and-forget Strong
Agent connector First-party MCP Community only None
Realtime channel state Streamed on change Poll it yourself Webhook
Event history Append-only log Your own logs Limited
Per-branch access roles Built in None Business manager

When you need to open conversations at scale with pre-approved templates, the official API is the honest answer. Ciro is for the conversation that is already yours.

Plainly

What Ciro is not.

The name means frank as much as it means free. Here is the part most vendors bury.

Not the official API, and not a licensed provider. Ciro is a public API on the WhatsApp Web protocol. Read the platform's terms and make your own call — we will not pretend that decision is ours to make for you.

Not a device-free product. A channel is bound to a real number and pairs by scanning a code from a real phone, the same as any web session.

Not a way to reach strangers. Ciro carries the conversation with people who already chose you. Cold blasting gets an account closed, and your delivery depends on everyone else behaving — so we police it.

Not the right tool for every job. If your case is opening conversations at scale with pre-approved templates, use the official channel. We would rather lose the sale than sell you the wrong thing.

Pricing

Per number. Never per message.

Charging per message would make us the toll, only cheaper. A flat price per connected number means your cost stops growing the moment your conversation starts.

Free 0 bring your own number
  • 1 number
  • 100 messages a day
  • One webhook endpoint
Solo $29 per number / month
  • Unlimited messages
  • Media sending
  • Webhooks with retry and DLQ
Pro $79 per number / month
  • Multiple companies
  • Role-based access per branch
  • Priority support
Platform $499 from · per month
  • Provisioning API
  • Sub-accounts and white-label widget
  • 25 numbers included

Prepaid in stablecoin gets 10–15% off. Cards are not offered: acquirers classify this category as prohibited, and an account frozen mid-month would be your outage, not just ours. We would rather be upfront than surprise you.

Get started

Sign up to use Ciro.

Tell us what you're building and we'll get in touch. Access opens in batches, because every number is a live session — we'd rather your first hour work than your first hour queue.

No card. No commitment. We reply to every signup.

In 539 BC, a king took the largest city on earth.

Everyone expected chains. He had the opposite carved into clay: go home, speak your language, worship as you please. It is the oldest declaration of freedom that survived, and his name was Cyrus.

Your customers. Your conversation. Your channel.

Ciro. Messaging that asks no one for permission.