Watily Developer Docs: WhatsApp, Loyalty & Webhooks API Skip to content
REST API · v1

Build on WhatsApp and loyalty with the Watily API

Send WhatsApp messages, manage contacts, campaigns and conversations, post loyalty points from the till and receive events in real time through signed webhooks. 45 endpoints with scoped keys, an OpenAPI spec and a Postman collection.

  • Bearer or X-Api-Key auth
  • HMAC-signed webhooks
  • OpenAPI 3 and Postman
curl -X POST https://site.watily.com/api/v1/messages \
  -H "Authorization: Bearer wtly_live_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "966501234567",
    "type": "text",
    "message": "Hi! Your order #1042 is ready for pickup"
  }'
What the API covers

Most of the Watily dashboard, available in code

WhatsApp Business

Send text, media, documents, templates, interactive messages, locations and reactions on official and QR lines, with an opt-out guard.

Contacts & campaigns

Import up to 500 contacts per call, segments, and create, start, pause and resume campaigns from your system.

Inbox

Read conversations and messages, assign them to agents, archive, tag, and track connected lines and analytics.

Loyalty & POS

One call from the till enrolls the customer and adds the stamp or points with no duplicates, plus reversals and wallet notifications.

Real-time events

12 events pushed to your URL: incoming messages, delivery status, campaigns, loyalty, line connect and disconnect.

Scoped security

Each key has specific scopes and its own rate limit, can be revoked instantly from the dashboard, and is stored hashed on our side.

Quickstart

From account to first message in three steps

Create an account and connect a line

Sign up for Watily and connect a WhatsApp number officially or by QR. Registration is free with a trial.

Create an API key

Go to WhatsApp, Integrations, API keys. Pick only the scopes you need. Keys start with wtly_live_ and are shown in full once.

Make your first call

Use the example above or import the Postman collection. Base URL: https://site.watily.com/api/v1

Authentication — either header works:

Authorization: Bearer wtly_live_xxxxxxxx
# or
X-Api-Key: wtly_live_xxxxxxxx

Common errors

HTTPMeaning
401invalid_api_key — missing or revoked key
403insufficient_scope / subscription_expired / quota_exceeded
402wallet_insufficient — official-line wallet cannot cover the send
409recipient_opted_out
422invalid_phone — 10 to 15 digits
429rate limit exceeded

Limits per key: 120 requests/min for reads and 60/min for writes and sends, which may vary by plan. Phone numbers are normalised automatically, so 0501234567 becomes 966501234567.

Endpoints

Every route under /api/v1

Each route lists the scope your key needs. Full field and response details are in the interactive reference.

Messages & media

MethodPathScopeDescription
POST/messagesmessages:sendSend a WhatsApp message (text, media, template, interactive, location)
POST/mediamessages:sendUpload media for a later message
GET/templatesmessages:sendList approved templates

Contacts & segments

MethodPathScopeDescription
GET/contactscontacts:readList contacts
GET/contacts/{phone}contacts:readGet a contact by phone
GET/contacts/{phone}/existscontacts:readDoes the number have WhatsApp (QR lines)
POST/contactscontacts:writeCreate a contact
PATCH/contacts/{phone}contacts:writeUpdate a contact
POST/contacts/importcontacts:writeBulk import up to 500 per call
POST/contacts/{phone}/unsubscribecontacts:writeUnsubscribe from marketing
POST/contacts/{phone}/resubscribecontacts:writeResubscribe
GET/segmentscontacts:readList segments
POST/segmentscontacts:writeCreate a segment

Campaigns

MethodPathScopeDescription
POST/campaignscampaigns:writeCreate a draft campaign
GET/campaigns/{campaign}campaigns:readGet a campaign
POST/campaigns/{campaign}/startcampaigns:writeStart
POST/campaigns/{campaign}/pausecampaigns:writePause
POST/campaigns/{campaign}/resumecampaigns:writeResume

Conversations, lines & analytics

MethodPathScopeDescription
GET/conversationsconversations:readList inbox conversations
GET/conversations/{id}conversations:readGet a conversation
GET/conversations/{id}/messagesconversations:readList its messages
POST/conversations/{id}/assignconversations:writeAssign or unassign
POST/conversations/{id}/tagsconversations:writeReplace tags
POST/conversations/{id}/archiveconversations:writeArchive (and unarchive)
POST/conversations/{id}/readconversations:writeMark as read
GET/instancesconversations:readConnected WhatsApp lines
GET/analytics/summaryconversations:readUsage summary for a range (last 30 days by default)

Loyalty & POS

MethodPathScopeDescription
POST/loyalty/stampsloyalty:writePOS flow: enroll + card + stamp in one call
POST/loyalty/stamps/reverseloyalty:writeReverse a stamp by idempotency_key
POST/loyalty/pointsloyalty:writePOS flow: enroll + award points in one call
POST/loyalty/points/reverseloyalty:writeReverse a points award
POST/loyalty/membersloyalty:writeEnroll a member
GET/loyalty/programsloyalty:readActive programs
GET/loyalty/members/{phone}loyalty:readGet a member
GET/loyalty/members/{phone}/pointsloyalty:readQuick balance and level check
GET/loyalty/members/{phone}/transactionsloyalty:readTransaction history
GET/loyalty/members/{phone}/wallet-cardloyalty:readApple / Google Wallet card links
GET/loyalty/cards/{cardNumber}loyalty:readLook up by printed or scanned card number
POST/loyalty/notificationsloyalty:notifyWallet lock-screen notification
GET/loyalty/notificationsloyalty:readNotification delivery history

Webhooks

MethodPathScopeDescription
GET/webhookswebhooks:manageList endpoints
POST/webhookswebhooks:manageRegister an endpoint (secret returned once)
PATCH/webhooks/{id}webhooks:manageUpdate
DELETE/webhooks/{id}webhooks:manageDelete
POST/webhooks/{id}/testwebhooks:manageSend a test delivery

Note: the Automation Journeys API was removed and its old route answers 410. Use the Growth Engine abandoned-cart automation instead.

Scopes

Give every integration the least access it needs

ScopeAllows
messages:sendSend messages, upload media, read templates
contacts:readRead contacts and segments
contacts:writeCreate and edit contacts and segments
campaigns:readRead campaigns
campaigns:writeCreate and control campaigns
conversations:readRead conversations, lines and analytics
conversations:writeAssign, archive and tag conversations
loyalty:readRead loyalty data
loyalty:writeRecord and reverse stamps and points
loyalty:notifyWallet notifications (separate scope on purpose)
webhooks:manageManage webhooks

Example: a POS system needs loyalty:write and loyalty:read only, so if its key leaks it cannot send messages or read conversations.

Recipes

What developers build most

Post a stamp from the till

One request enrolls the customer, issues the card and adds the stamp. Re-sending the same idempotency_key never doubles it.

curl -X POST https://site.watily.com/api/v1/loyalty/stamps \
  -H "X-Api-Key: wtly_live_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "966501234567",
    "idempotency_key": "pos-order-882",
    "amount": 45.5,
    "branch": "Main branch"
  }'

Register a webhook

The URL must be public HTTPS. Keep the secret returned in the response; it is shown once. Omit events to subscribe to all.

curl -X POST https://site.watily.com/api/v1/webhooks \
  -H "Authorization: Bearer wtly_live_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/watily-hook",
    "events": ["message.incoming", "message.status"]
  }'
Webhooks

Receive events and verify their signature

Each delivery carries the headers X-Watily-Event X-Watily-Delivery X-Watily-Signature. The signature is sha256=HMAC_SHA256(raw_body, secret).

message.incomingmessage.statuscampaign.completedcontact.unsubscribedcontact.resubscribedloyalty.visit.recordedloyalty.reward.unlockedloyalty.visit.reversedloyalty.points.awardedloyalty.points.reversedinstance.connectedinstance.disconnected
<?php
$raw = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_WATILY_SIGNATURE'] ?? '';
$calc = 'sha256=' . hash_hmac('sha256', $raw, $endpointSecret);

if (!hash_equals($calc, $sig)) {
    http_response_code(401);
    exit;
}
$event = json_decode($raw, true); // $event['event'], $event['data']
http_response_code(200);

Compute the signature on the raw body before any JSON parsing, compare it with a constant-time function and answer 200 quickly.

FAQ

Developer questions

How do I get an API key?

In the Watily dashboard go to WhatsApp, then Integrations, then API keys. Create a key and tick only the scopes your integration needs. The full key is shown once at creation, so store it safely; you can revoke it at any time.

What is the base URL and how do I authenticate?

The base URL is https://site.watily.com/api/v1. Send the key as an Authorization Bearer header or in an X-Api-Key header; both behave the same.

Are there rate limits?

Yes. Each key gets 120 requests per minute for reads and 60 per minute for writes and sends, which can vary by plan. Going over returns HTTP 429; retry shortly after.

Can I receive incoming messages and updates in real time?

Yes, through webhooks: register an HTTPS URL and choose events (incoming message, message status, campaign completed, unsubscribes, loyalty events, line connected or disconnected). Every delivery is signed with an X-Watily-Signature header you verify with HMAC SHA-256.

Does the API cover loyalty and POS?

Yes. A one-call flow for tills and ERPs enrolls the customer and adds the stamp or points, an idempotency_key prevents double-posting, and there are endpoints to reverse, check balances, fetch wallet-card links and push lock-screen notifications.

Is there an OpenAPI spec or Postman collection?

Yes. The full interactive reference, an OpenAPI 3 spec and a ready Postman collection are available from the reference page and stay in sync with every API change.

Does sending differ by connection type?

The same request works on official lines (Meta Cloud API) and QR lines. Template messages, wallet balance and the 24-hour window rules apply to official lines as Meta defines them, and usage beyond the plan quota is billed at Meta’s direct rate.

Ready to integrate?

Create your account, grab your key, and message us on WhatsApp if you need help wiring up your system.

WhatsApp Start now