Your application.
Connected to WhatsApp.
Push leads in from any system and let Rechlio run outreach automatically, send WhatsApp messages programmatically, and receive inbound events on your own endpoint. Base URL: https://outreachapi-9bdb.replov.com
Make your first request
01 · Connect
Connect your WhatsApp Business number in the WhatsApp dashboard.
02 · Authorize
Create a scoped key and save its secret when it is shown once.
03 · Integrate
Call the API from your backend and configure response webhooks.
Keep your key in a backend environment variable. Never expose it in browser JavaScript, public environment variables or mobile-app source.
export RECHLIO_API_KEY="your-api-key"
curl https://outreachapi-9bdb.replov.com/v1 \
-H "Authorization: Bearer $RECHLIO_API_KEY"{ "ok": true, "api": "rechlio", "version": "v1" }For your first send, use an approved template and a recipient you have permission to contact. Template names, language and parameters must match your approved template.
Authentication
Create an API key in Dashboard → API. The key is shown once — store it securely. Send it as a Bearer token (or an X-API-Key header) on every request. Keys are scoped, and a key is granted only what you tick when you create it: leads:write, leads:read and whatsapp:send.
Authorization: Bearer rk_live_...The key determines your workspace; do not supply another workspace ID. To rotate a key, create a replacement, update your backend, verify a request, then revoke the old key. Revocation takes effect on the next request.
Ingest a lead
Creates a lead. At least an email or a phone is required. Re-posting the same contact updates it (idempotent). If auto-run is enabled, the lead is routed to a playbook and outreach starts on the first channel it can receive.
/v1/leadsScope: leads:write
curl -X POST https://outreachapi-9bdb.replov.com/v1/leads \
-H "Authorization: Bearer rk_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Corp",
"email": "owner@acme.com",
"phone": "+919876543210",
"source": "website_form",
"tags": ["pricing"],
"consent": { "whatsapp": true, "email": true },
"external_id": "your-crm-id-123"
}'Response
{ "lead_id": "…", "status": "created", "enrolled": true, "campaign_id": "…" }A name is also required. Matching uses normalized phone when provided, otherwise email. external_id is a reference/filter, not the deduplication key. Updating an existing lead does not re-enroll it. Auto-run must be configured in Dashboard → API; otherwise enrolled is false and campaign_id is null. The WhatsApp Idempotency-Key contract does not apply to lead ingestion.
Read your leads
Closes the loop the ingest endpoint opens: push a contact in, then read back what segmentation decided and which campaign it was enrolled in. Only ever returns leads belonging to the key’s own workspace.
/v1/leadsScope: leads:read
Filters: status, source, external_id, updated_since (ISO 8601). Paging: page and limit (default 50, max 100), newest change first.
curl "https://outreachapi-9bdb.replov.com/v1/leads?status=replied&updated_since=2026-09-01T00:00:00Z&limit=50" \
-H "Authorization: Bearer rk_live_..."Response
{
"leads": [
{
"lead_id": "…",
"external_id": "your-crm-id-123",
"dedupe_key": "API-PH-919876543210",
"name": "Acme Corp",
"email": "owner@acme.com",
"phone": "+919876543210",
"status": "replied",
"source": "website_form",
"tags": ["pricing"],
"consent": { "whatsapp": true },
"score": 82,
"campaign_id": "…",
"segment": { "persona": "…", "language": "hinglish", "pain_points": ["…"] },
"created_at": "…",
"updated_at": "…"
}
],
"pagination": { "page": 1, "limit": 50, "total": 1, "total_pages": 1 }
}One lead
/v1/leads/:idReturns the same object. A lead in another workspace answers 404, not 403 — a key cannot be used to discover that an id exists somewhere else.
Send a WhatsApp message
Send an approved template anytime, or free-form text within the 24-hour customer window. The message appears in your inbox and receives delivery-status updates. Requires a connected WhatsApp account.
/v1/whatsapp/messagesScope: whatsapp:send
Template
curl -X POST https://outreachapi-9bdb.replov.com/v1/whatsapp/messages \
-H "Authorization: Bearer rk_live_..." \
-H "Idempotency-Key: order-123-confirmation-v1" \
-H "Content-Type: application/json" \
-d '{
"to": "+919876543210",
"type": "template",
"template": {
"name": "welcome",
"language": "en_US",
"headerType": "image",
"headerParam": "https://example.com/banner.jpg",
"bodyParams": ["Shivraj"],
"buttonParams": [{ "index": 0, "text": "ORDER123" }]
}
}'Session text (within 24h)
{ "to": "+919876543210", "type": "text", "text": "Thanks for reaching out!" }Response
{ "message_id": "wamid.…", "status": "sent" }This synchronous response means Meta accepted the message, not that it has been delivered. Store message_id for webhook correlation. Media header links must use public HTTPS without credentials and be accessible to Meta. This endpoint does not upload files or create templates. Obtain and record recipient consent; sending a request does not collect consent.
const { RECHLIO_API_KEY } = process.env;
if (!RECHLIO_API_KEY) throw new Error('Set your backend API key first');
const operationKey = 'order-123-confirmation-v1'; // persist with your order
const response = await fetch('https://outreachapi-9bdb.replov.com/v1/whatsapp/messages', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + RECHLIO_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': operationKey,
},
body: JSON.stringify({
to: '+919876543210', type: 'template',
template: { name: 'welcome', language: 'en_US', bodyParams: ['Asha'] },
}),
});
const result = await response.json();
if (!response.ok) throw new Error(result.error || 'Send was not confirmed');
// Save result.message_id with the corresponding business record.Retries & idempotency
Use one persistent Idempotency-Key per logical message, up to 255 characters. Reuse the same key and request body after a client timeout. Keys are scoped to workspace and endpoint.
- Same key and body: replay the stored outcome with
Idempotent-Replay: true. - Same key with a different body:
422. - Still running:
409. Retry the same request later. A stale claim asks for reconciliation. - Provider timeout or uncertain server outcome: the claim is retained, including stored 5xx responses, to prevent another send.
The header is optional for compatibility; sends without it have no request-replay protection. There is currently no automatic key expiry. Keep your operation key with its business record.
Receive events (webhooks)
Configure an endpoint in Dashboard → API → Response webhooks. Rechlio POSTs an event when a lead messages your number (message.received), on delivery/read status (message.status), and when a lead replies (lead.replied). Failed deliveries retry with exponential backoff.
Example delivery
POST https://your-app.com/webhooks/rechlio
X-Rechlio-Event: message.received
X-Rechlio-Signature: 9f2c… (HMAC-SHA256 of the raw body)
{
"event": "message.received",
"workspaceId": "…",
"timestamp": "2026-08-26T10:00:00.000Z",
"data": { "from": "919876543210", "type": "text", "text": "Hi!", "messageId": "wamid.…" }
}Verifying the signature
Compute an HMAC-SHA256 of the raw request body using your webhook signing secret (shown on the API page) and compare it to the X-Rechlio-Signature header.
import crypto from 'crypto';
function verify(rawBody, signature, secret) {
if (!secret || typeof signature !== 'string' ||
!/^[a-f0-9]{64}$/i.test(signature)) return false;
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest();
const received = Buffer.from(signature, 'hex');
return received.length === expected.length &&
crypto.timingSafeEqual(received, expected);
}Read the original body bytes before JSON parsing. Reject an invalid signature, durably accept or enqueue the verified event, then return a 2xx promptly. Configure a public HTTPS endpoint: redirects and private destinations are refused. Keep responses under 64 KiB.
{
"messageId": "wamid.example", "status": "delivered",
"recipient": "919876543210", "error": null,
"at": "2026-09-09T10:00:00.000Z"
}For message.status, correlate data.messageId with your send response. Webhook retries can produce duplicate events. Deduplicate incoming messages by message ID, and status updates by message ID plus status so a later read update is not discarded. Tolerate out-of-order updates. The top-level timestamp may change on retries. Delivery attempts are visible in the dashboard.
Limits & billing
120 / minute
per source IP
300 / minute
per API key
600 / minute
per workspace
All three limits apply, including to reads and replayed requests. Multiple keys do not increase the workspace ceiling. On 429, back off with jitter and retain your original message key. These limits are fixed, not plan-specific.
WhatsApp API sends record usage and use your configured platform fee. The default platform fee is ₹0; Meta charges are separate. A configured fee can return 402 when balance is insufficient. Definitive failures refund usage; uncertain delivery remains held for reconciliation.
STOP and other recognized opt-outs suppress future sends. Suppressed and do-not-contact recipients are blocked. An unconnected workspace cannot silently borrow the platform’s number; shared-number mode is an explicit operator setting.
Troubleshoot a request
Errors return a JSON body { "error": "…" } with a standard HTTP status. Save the operation key and any confirmed message ID alongside your business record.
| Status | What to do |
|---|---|
| 400 | Check fields, WhatsApp connection, approved template and the 24-hour text window. |
| 401 | Supply a valid, non-revoked API key. |
| 402 | Check the workspace balance and configured send fee. |
| 403 | Check key scope and recipient suppression/do-not-contact status. |
| 404 | Check the lead ID and workspace associated with the key. |
| 409 | The operation is running or needs reconciliation. Keep the same key. |
| 422 | The key was used with a different body. Check the original operation. |
| 429 | Back off; an IP, key or workspace rate limit was reached. |
| 5xx | A send may have been accepted. Reuse its key to inspect the stored outcome; do not blindly create another send. |
What is available today?
Available: scoped API keys, lead ingestion and lookup, template/session-text sends, signed webhooks and existing campaign auto-run routing.
Not available yet: POST /v1/events, canonical contacts endpoints, public automation CRUD/run endpoints, and a local template/media API. Do not build integrations against these planned endpoints.
The larger event → condition → wait → send automation platform is still in development. You can integrate direct messaging and lead-driven campaigns using the endpoints above once your account and WhatsApp connection are configured.
Need help? Contact support@rechlio.com.