Socialrocx API
Send WhatsApp messages from your own software (billing, ERP, website) through your business's Socialrocx account, and get events back by webhook. Every message appears in the Socialrocx inbox, so your team sees the whole conversation.
https://zzvmikkgqvebbnxgoozx.supabase.co/functions/v1/apiAuthentication
The business owner creates a key in Socialrocx → Developers → API keys. Send it in every request:
Authorization: Bearer srx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys are shown once. Keep them on your server, never in a website or phone app. Revoke a key any time from the same page.
Rules & limits
- WhatsApp's 24-hour rule: free text, documents and images only go to customers who messaged in the last 24 hours. Otherwise send an approved template (create them in Socialrocx → Campaigns → Templates).
- Phone numbers need the country code. Indian 10-digit numbers get
91added:98400 12345→919840012345. - Files are sent by
httpslink (for example your bill PDF). WhatsApp downloads it. - Rate limit: 120 requests a minute per key (HTTP 429 with
Retry-After). - Safe retries: send an
Idempotency-Keyheader (e.g. your bill number). Repeating a request with the same key returns the first answer and sends nothing new (headerIdempotent-Replay: true). - Marketing consent: set
opt_inonly with anopt_in_sourcesaying how the customer agreed. Socialrocx records it.
Errors
Errors return JSON {"error": {"code": "...", "message": "..."}}.
| HTTP | code | Meaning |
|---|---|---|
| 400 | bad_phone, bad_type, params_mismatch, header_file_required, bad_file, opt_in_source_required | Fix the request. |
| 401 | unauthorized | Missing, wrong or revoked key. |
| 404 | template_not_approved, not_found | No approved template with that name, or no such item. |
| 409 | window_closed, not_connected, in_progress | Use a template; connect WhatsApp; same Idempotency-Key still running. |
| 429 | rate_limited | Wait for Retry-After seconds. |
| 502 | whatsapp_error | WhatsApp refused the message; message says why. The message is still saved in the chat as failed. |
GET/v1/me
Check the key and see which business and WhatsApp number it sends from.
curl $BASE/v1/me -H "Authorization: Bearer $KEY"
{ "business": { "id": "…", "name": "Helen Lightings India" },
"whatsapp": { "phone": "+91 …", "name": "Helen Lightings India", "quality": "GREEN", "limit_tier": "TIER_1K" },
"key": { "name": "Payrocx" } }
GET/v1/templates
Approved templates, with how many {{n}} blanks each needs and whether it has a document/image header.
{ "data": [ { "name": "bill_ready", "language": "en", "category": "UTILITY",
"body": "Hi {{1}}, your bill {{2}} is attached.", "header_format": "DOCUMENT", "params": 2 } ] }
POST/v1/messages
| Field | Type | |
|---|---|---|
to | string | Customer's number with country code. |
type | template | text | document | image | |
contact_name | string, optional | Saved on the contact. |
template | object | { name, language?, params: ["..."], header?: { url, filename } } |
text | string | For type: "text" (inside 24 hours). |
document / image | object | { url, filename?, caption? } (inside 24 hours). |
curl -X POST $BASE/v1/messages \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: bill-INV-2611" \
-d '{ "to": "+91 98400 12345", "contact_name": "Ramesh", "type": "template",
"template": { "name": "bill_ready", "params": ["Ramesh", "INV-2611"],
"header": { "url": "https://your-server.example.com/bills/INV-2611.pdf", "filename": "INV-2611.pdf" } } }'
201 { "id": "…", "conversation_id": "…", "status": "sent", "wa_message_id": "wamid.…" }
status is sent when WhatsApp accepted it. Delivered and read come later by the message.status webhook (or poll the next endpoint).
GET/v1/messages/:id
{ "id": "…", "status": "read", "kind": "template", "body": "Hi Ramesh, your bill INV-2611 is attached.", "error": null, … }
Status goes sending → sent → delivered → read, or failed with an error.
Contacts
GET/v1/contacts?phone=919840012345: name, tags, language, opt-in and where it came from, custom details.
POST/v1/contacts: create or update.
{ "phone": "9840012345", "name": "Ramesh", "tags": ["contractor"], "language": "Tamil",
"opt_in": true, "opt_in_source": "ticked 'send me offers' on bill INV-2611" }
Webhooks
Add a webhook in Socialrocx → Developers → Webhooks with your https address and the events you want. Socialrocx POSTs JSON like this:
{ "id": "evt id", "event": "message.status", "created_at": "2026-11-07T10:15:00Z",
"data": { "message_id": "…", "wa_message_id": "wamid.…", "conversation_id": "…", "direction": "out",
"kind": "template", "text": "Hi Ramesh, your bill INV-2611 is attached.", "status": "read",
"contact": { "id": "…", "phone": "+919840012345", "name": "Ramesh" }, "error": null, "created_at": "…" } }
| Event | When |
|---|---|
message.received | A customer sends a message (data as above, direction: "in"). |
message.status | Your message becomes sent, delivered, read or failed. |
contact.opted_out | A customer stops offers (STOP or the "Stop offers" button). Stop sending them marketing. |
order.created | A customer orders from the WhatsApp cart (items, total_paise, contact). |
test | The "Send test" button. |
Answer with any 2xx within 10 seconds. Otherwise Socialrocx retries after 1 min, 5 min, 30 min, 2 h and 6 h. The same event can arrive twice: use id to ignore duplicates.
Verify signatures
Each call has X-Socialrocx-Timestamp and X-Socialrocx-Signature: sha256=…, the HMAC-SHA256 of "<timestamp>.<raw body>" with your webhook's signing secret. Reject calls that don't match or are older than 5 minutes.
// Node.js (Express): use the raw body, not parsed JSON
import crypto from 'node:crypto';
app.post('/socialrocx-webhook', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-Socialrocx-Timestamp');
const expected = 'sha256=' + crypto.createHmac('sha256', process.env.SOCIALROCX_WEBHOOK_SECRET)
.update(`${ts}.${req.body}`).digest('hex');
const given = req.get('X-Socialrocx-Signature') ?? '';
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
if (!fresh || given.length !== expected.length || !crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected)))
return res.sendStatus(401);
const event = JSON.parse(req.body);
// … handle event.event / event.data …
res.sendStatus(204);
});
# Python (Flask)
import hmac, hashlib, time, os
@app.post("/socialrocx-webhook")
def hook():
ts, body = request.headers["X-Socialrocx-Timestamp"], request.get_data()
expected = "sha256=" + hmac.new(os.environ["SOCIALROCX_WEBHOOK_SECRET"].encode(), f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
if abs(time.time() - int(ts)) > 300 or not hmac.compare_digest(expected, request.headers.get("X-Socialrocx-Signature", "")):
return "", 401
event = request.get_json()
return "", 204
Recipe: send bills from billing software
- In Socialrocx, create a Utility template with a document header, e.g.
bill_ready: “Hi {{1}}, your bill {{2}} is attached.” Wait for Meta's approval. - Create an API key named after your billing software and store it on its server.
- After each bill, upload the PDF where it has an https link, then call
POST /v1/messageswithtype: "template", the customer's number,paramsandheader.url. Use the bill number asIdempotency-Key. - Optional: add a webhook for
message.statusto show “Sent ✓✓ / Read” on the bill, andmessage.receivedto see replies.
Customers who reply land in the Socialrocx inbox, so your team can answer questions about the bill.