Developers
REST & webhooks. Plug Niyog into your stack.
Push leads in, send WhatsApp messages, subscribe to outcome events. Every endpoint is tenant-scoped. Webhooks are HMAC-signed. Keys are minted from the admin console.
Live today
REST v1 · signed webhooks (HMAC-SHA256) · API key minting · per-key scopes · MCP server (mcp__niyog-mcp__*) for Claude clients
Coming next
Official TypeScript + Python SDKs · OAuth for third-party apps · public OpenAPI spec · GraphQL surface for the dashboard
Authentication
Every request needs an Authorization: Bearer niyog_live_… header. Mint a key from the admin console. Keys are shown once on creation.
curl https://niyogai.com/api/v1/leads \
-H "Authorization: Bearer niyog_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"Create a lead
POST /api/v1/leads
curl -X POST https://niyogai.com/api/v1/leads \
-H "Authorization: Bearer $NIYOG_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Rohan Mehta",
"phone": "919812345678",
"source": "shopify",
"intent": "Asked about pricing on the checkout page"
}'
# Response (201)
{ "id": 4821, "phone": "919812345678", "name": "Rohan Mehta", "created": true, "stage": "New" }Node
const res = await fetch('https://niyogai.com/api/v1/leads', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.NIYOG_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Rohan Mehta',
phone: '919812345678',
source: 'shopify',
intent: 'Asked about pricing on the checkout page',
}),
})
const lead = await res.json()Python
import os, requests
res = requests.post(
'https://niyogai.com/api/v1/leads',
headers={'Authorization': f"Bearer {os.environ['NIYOG_KEY']}"},
json={
'name': 'Rohan Mehta',
'phone': '919812345678',
'source': 'shopify',
'intent': 'Asked about pricing on the checkout page',
},
)
lead = res.json()List & read leads
# All leads in your workspace, newest first.
GET /api/v1/leads?limit=20&stage=Warm
# Single lead by ID.
GET /api/v1/leads/:id
# Update stage or intent.
PATCH /api/v1/leads/:id
{ "stage": "Qualified" }Send a WhatsApp message
POST /api/v1/messages — sends through your workspace’s WhatsApp Business Account. If the first attempt fails Meta, it auto-queues for retry with exponential backoff.
curl -X POST https://niyogai.com/api/v1/messages \
-H "Authorization: Bearer $NIYOG_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "919812345678",
"body": "Hi Rohan, saw you were looking at the pro plan. Free trial works for you?"
}'
# Response
{ "sent": true, "message_id": "wamid.HBgL...", "to": "919812345678" }List agents
GET /api/v1/agents
{
"data": [
{ "slug": "sales.qualifier", "name": "Priya", "category": "sales", "status": "live", "description": "..." },
{ "slug": "sales.demo_booker", "name": "Meera", "category": "sales", "status": "live", "description": "..." },
...
],
"count": 26
}Webhooks
Subscribe a URL to receive outcome events. Every delivery is signed with HMAC-SHA256 using the per-subscription secret returned on creation.
curl -X POST https://niyogai.com/api/v1/webhooks \
-H "Authorization: Bearer $NIYOG_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/niyog",
"events": ["lead.qualified", "meeting.booked", "message.sent"]
}'
# Response (201)
{
"id": 17,
"url": "https://example.com/webhooks/niyog",
"events": ["lead.qualified", "meeting.booked", "message.sent"],
"secret": "whsec_abcdef...",
"message": "Save this secret — it will not be shown again."
}Event payload shape
POST https://your-url/webhooks/niyog
X-Niyog-Event: lead.qualified
X-Niyog-Signature: t=1716042131,v1=<hex_hmac>
{
"event": "lead.qualified",
"client_id": 17,
"agent_slug": "sales.qualifier",
"metadata": { "lead_id": 4821, "stage": "Qualified", "score": 8, "intent": "..." },
"value_cents": null,
"delivered_at": "2026-05-18T03:42:11.000Z"
}Verify the signature (Node)
The signature header has the form t=<unix_ts>,v1=<hex_hmac>. The HMAC covers <unix_ts>.<raw_body>. Reject deliveries where |now - t| > 300 seconds — that’s a replay.
import crypto from 'node:crypto'
function verify(req, secret) {
const header = req.headers['x-niyog-signature'] // "t=1716042131,v1=..."
const parts = Object.fromEntries(header.split(',').map(kv => kv.split('=')))
const ts = parseInt(parts.t, 10)
if (Math.abs(Date.now() / 1000 - ts) > 300) return false // replay protection
const signed = ts + '.' + req.rawBody.toString('utf8')
const expected = crypto.createHmac('sha256', secret).update(signed).digest('hex')
return crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected))
}Available events
lead.created — A new lead enters the workspace (any source).
lead.qualified — Priya (or your custom qualifier) classifies a lead.
message.sent — An outbound WhatsApp message delivered successfully.
deal.updated — A deal's stage or value changes.
meeting.booked — Meera (or your booking agent) confirms a demo slot.
agent.run.completed — Any agent cron finishes (success or failure).Need a key, custom scope, higher rate limit, or stuck on something? WhatsApp the founder.