GaptixAPI reference · v2
Get started

Gaptix WhatsApp API

Send WhatsApp messages from your website, app or CRM, keep contacts in sync and get customer replies in real time — with one simple JSON API on top of the official WhatsApp Business Platform.

BASE https://gaptix.com/api.php?action={action}
  1. Connect WhatsApp in your Gaptix dashboard (Settings).
  2. Create an API key in Developer → API keys. It starts with wak_.
  3. Call the API — try status first, then send a template.

Authentication

Send your API key with every request in the X-API-Key header. Authorization: Bearer wak_… also works. Keep keys secret — use them only from your server, never in a browser or mobile app.

Each key can be limited to your server’s IP addresses and switched off at any time in Developer → API keys.

Request format

Pick the action with ?action=… (or the path, e.g. /api.php/send_text). Send parameters as JSON with Content-Type: application/json, as form fields, or — for GET actions — in the query string.

Test your key
curl "https://gaptix.com/api.php?action=status" \
  -H "X-API-Key: wak_your_api_key"

Responses & errors

Every response is JSON with success and a request_id (also in the X-Request-Id header — quote it when contacting support). Errors carry a human-readable error and a stable error_code you can branch on.

HTTPerror_codeMeaning
400invalid_json / missing_actionThe request could not be read
401unauthorizedMissing, wrong or unknown API key
402insufficient_balanceWallet too low to open a new conversation — recharge
403key_disabled / ip_not_allowed / api_disabledKey switched off, IP not on the key’s allow-list, or API disabled for the account
404unknown_action / not_found / template_not_foundThe action, message, contact or template doesn’t exist
409duplicateA contact with this phone already exists
422missing_parameter, invalid_phone, template_param_mismatch, missing_header, …A parameter is missing or invalid — the message says exactly what to fix
429rate_limitedMore than 120 requests a minute — wait for Retry-After seconds
502meta_error, outside_24h_window, undeliverable, …WhatsApp refused the message. meta_code holds WhatsApp’s own error code
503whatsapp_not_connected / token_expiredYour WhatsApp number isn’t connected or its token expired
Error example
{
    "success": false,
    "error": "Template 'order_confirmed' needs 3 variable(s) but 2 were given.",
    "error_code": "template_param_mismatch",
    "request_id": "req_8f2c1a9d4b7e6031"
}

Limits & billing

  • Rate limit: 120 requests per minute per key. Every response has X-RateLimit-Remaining; over the limit you get 429 with Retry-After.
  • 24-hour window: free-form messages (text, media, buttons, lists…) can only be sent within 24 hours of the customer’s last message. Outside it, send an approved template.
  • Billing: sends are checked against your wallet first (402 insufficient_balance). You are charged per 24-hour conversation only when WhatsApp confirms delivery — failed messages cost nothing.
  • Messaging limit: how many new customers you can start conversations with per day is set by WhatsApp (see WhatsApp Health in the dashboard).
  • Messages sent through the API also appear in your Live Chat inbox and chat history.

Webhook events

Register a URL with register_webhook (or in Developer → Webhooks). We send a POST with a JSON body for each event and the header X-Gaptix-Event. Reply with any 2xx within 10 seconds.

messageA customer sent you a message (text, button reply, list reply, media…).
message.statusA message you sent changed status: sent, delivered, read or failed (with error).

Verifying signatures

If you set a secret, each request has X-WA-Signature: sha256=<hex> — an HMAC-SHA256 of the raw body using your secret. Compute it yourself and compare before trusting the event.

PHP — verify
$body = file_get_contents('php://input');
$sig  = $_SERVER['HTTP_X_WA_SIGNATURE'] ?? '';
$ok   = hash_equals('sha256=' . hash_hmac('sha256', $body, 'your-secret'), $sig);
if (!$ok) { http_response_code(401); exit; }
$event = json_decode($body, true);
message
{
    "event": "message",
    "from": "919876543210",
    "contact_name": "Riya Sharma",
    "type": "text",
    "text": "Is it available in blue?",
    "message_id": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAEhgU",
    "phone_number_id": "1314759468377345",
    "timestamp": 1790237113
}
message.status
{
    "event": "message.status",
    "message_id": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgS",
    "status": "delivered",
    "to": "919876543210",
    "timestamp": 1790237066,
    "phone_number_id": "1314759468377345",
    "error": null
}
Account

Account status

GET /api.php?action=status

Checks your API key and WhatsApp connection. Returns the connected number, quality rating and wallet balance. Good first call to test your setup.

No parameters.

Request

      
Response
{
    "success": true,
    "status": "connected",
    "account": {
        "phone_number": "+91 98765 43210",
        "phone_number_id": "1314759468377345",
        "verified_name": "Pitch Point",
        "phone_status": "CONNECTED",
        "quality_rating": "GREEN",
        "throughput": "STANDARD",
        "waba_id": "2011356992820445"
    },
    "wallet": {
        "balance": 499.65,
        "currency": "INR"
    },
    "api_key": {
        "name": "Production",
        "requests_today": 42,
        "requests_total": 1830
    },
    "request_id": "req_8f2c1a9d4b7e6031"
}
Account

Wallet balance

GET /api.php?action=wallet

Your WhatsApp wallet: balance, money on hold for messages not yet delivered, and your per-conversation rates.

No parameters.

Request

      
Response
{
    "success": true,
    "wallet": {
        "balance": 499.65,
        "currency": "INR",
        "billing_mode": "prepaid",
        "on_hold": 0.15,
        "awaiting_delivery": 3,
        "rates_per_conversation": {
            "marketing": 0.1,
            "utility": 0.05,
            "authentication": 0.05,
            "service": 0.05
        },
        "free_service_per_month": 1000
    },
    "request_id": "req_8f2c1a9d4b7e6031"
}
Send messages

Send a template message

POST /api.php?action=send_message

Sends an approved WhatsApp template. Works any time — including outside the 24-hour window. Aliases: send_template.

Parameters

torequiredstringRecipient number with country code, digits only — e.g. 919876543210
template_namerequiredstringName of an APPROVED template
languagestringTemplate language code, e.g. en_US. Defaults to the approved version.
variablesarray | objectBody variables in order: ["Riya","ORD-1042"]. For templates with named variables pass an object: {"name":"Riya"}.
headerobjectRequired when the template has a media or variable header. {"link":"https://…/photo.jpg"}, {"id":"<media_id>"}, {"text":"…"}, or for documents add "filename".
button_url_valuestringValue for the {{1}} at the end of a dynamic website button (first one).
buttonsarrayPer-button values: [{"index":0,"value":"ORD-1042"}]. Also for coupon_code buttons, quick-reply payload and flow flow_token.
coupon_codestringShortcut for templates with a copy-code button.
componentsarrayAdvanced: Meta components array sent as-is (e.g. carousel templates).
reply_tostringMessage id to quote/reply to.
Authentication (OTP) templates: pass the code as variables: ["482913"] — it is placed in the body and the copy-code button automatically.
Request

      
Response
{
    "success": true,
    "message_id": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgS",
    "to": "919876543210",
    "template": "order_confirmed",
    "language": "en_US",
    "category": "utility",
    "request_id": "req_8f2c1a9d4b7e6031"
}
Send messages

Send a text message

POST /api.php?action=send_text

Free-form text. Only allowed within 24 hours of the customer’s last message to you (the customer service window).

Parameters

torequiredstringRecipient number
messagerequiredstringUp to 4096 characters. Supports *bold*, _italic_, ~strike~.
preview_urlbooleanShow a link preview for the first URL
reply_tostringMessage id to reply to
Request

      
Response
{
    "success": true,
    "message_id": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgS",
    "to": "919876543210",
    "request_id": "req_8f2c1a9d4b7e6031"
}
Send messages

Send image, video, audio or document

POST /api.php?action=send_media

Send a file by public URL or by a media_id from upload_media. 24-hour window applies.

Parameters

torequiredstringRecipient number
typerequiredstringimage, video, audio, document or sticker
linkstringPublic https URL of the file
media_idstringId returned by upload_media (use instead of link)
captionstringFor image, video, document
filenamestringShown for documents
Limits: images 5 MB (JPG/PNG), video 16 MB (MP4), audio 16 MB, documents 100 MB.
Request

      
Response
{
    "success": true,
    "message_id": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgS",
    "to": "919876543210",
    "type": "document",
    "request_id": "req_8f2c1a9d4b7e6031"
}
Send messages

Send buttons, a list or a link button

POST /api.php?action=send_interactive

Interactive messages customers can tap. 24-hour window applies.

Parameters

torequiredstringRecipient number
typerequiredstringbuttons (up to 3 reply buttons), list (menu of up to 10 rows) or cta_url (one link button)
bodyrequiredstringMessage text
headerstring | objectText, or {"type":"image","link":"…"}
footerstringSmall grey text
buttonsarrayFor buttons: [{"id":"yes","title":"Yes"}] — titles up to 20 characters
sectionsarrayFor list: [{"title":"…","rows":[{"id":"r1","title":"…","description":"…"}]}]
buttonstringList menu label, or the link button text for cta_url
urlstringFor cta_url
When the customer taps a button you receive a message webhook with type: "interactive" and the button id.
Request

      
Response
{
    "success": true,
    "message_id": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgS",
    "to": "919876543210",
    "type": "buttons",
    "request_id": "req_8f2c1a9d4b7e6031"
}
Send messages

Send a location

POST /api.php?action=send_location

A map pin.

Parameters

torequiredstringRecipient number
latituderequirednumber
longituderequirednumber
namestringPlace name
addressstringAddress line
Request

      
Response
{
    "success": true,
    "message_id": "wamid.HBgM…",
    "to": "919876543210",
    "request_id": "req_8f2c1a9d4b7e6031"
}
Send messages

Send contact cards

POST /api.php?action=send_contacts

Share one or more contact cards.

Parameters

torequiredstringRecipient number
contactsrequiredarray[{"name":"Asha Rao","phone":"919812345678","email":"…","company":"…"}]
Request

      
Response
{
    "success": true,
    "message_id": "wamid.HBgM…",
    "to": "919876543210",
    "request_id": "req_8f2c1a9d4b7e6031"
}
Send messages

React to a message

POST /api.php?action=send_reaction

Adds an emoji reaction to a message in the chat. Pass an empty emoji to remove it.

Parameters

torequiredstringRecipient number
message_idrequiredstringMessage to react to
emojistringDefault 👍
Request

      
Response
{
    "success": true,
    "message_id": "wamid.HBgM…",
    "to": "919876543210",
    "request_id": "req_8f2c1a9d4b7e6031"
}
Send messages

Mark as read

POST /api.php?action=mark_read

Shows blue ticks for an incoming message. Optionally show “typing…” while you prepare a reply.

Parameters

message_idrequiredstringId of the incoming message
typingbooleanAlso show a typing indicator (up to 25 seconds)
Request

      
Response
{
    "success": true,
    "message_id": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAEhgU",
    "read": true,
    "request_id": "req_8f2c1a9d4b7e6031"
}
Send messages

Send a template to many numbers

POST /api.php?action=send_bulk

Up to 1,000 recipients per call. Each recipient can have its own variables. Numbers that fail are reported individually — the rest still send.

Parameters

template_namerequiredstringApproved template
recipientsrequiredarray["9198…","9197…"] or [{"to":"9198…","variables":["Riya"]}]
variablesarrayShared variables for plain-number recipients
languagestring
header / buttons / button_url_valueSame as send_message (shared, or per recipient)
Request

      
Response
{
    "success": true,
    "template": "diwali_offer",
    "total": 2,
    "sent": 2,
    "failed": 0,
    "results": [
        {
            "to": "919876543210",
            "success": true,
            "message_id": "wamid.HBgM…"
        },
        {
            "to": "919812345678",
            "success": true,
            "message_id": "wamid.HBgM…"
        }
    ],
    "request_id": "req_8f2c1a9d4b7e6031"
}
Messages & status

Message status

GET /api.php?action=message_status

Delivery status of a message you sent: sent → delivered → read, or failed with the reason. Also shows whether it has been billed.

Parameters

message_idrequiredstringThe id returned when you sent it
Prefer the message.status webhook for real-time updates instead of polling.
Request

      
Response
{
    "success": true,
    "message": {
        "message_id": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgS",
        "to": "919876543210",
        "direction": "out",
        "type": "template",
        "template": "order_confirmed",
        "status": "delivered",
        "error": null,
        "sent_at": "2026-09-24 10:21:04",
        "updated_at": "2026-09-24 10:21:06",
        "billing": {
            "state": "charged",
            "charged": 0.05
        }
    },
    "request_id": "req_8f2c1a9d4b7e6031"
}
Messages & status

Chat history with a number

GET /api.php?action=list_messages

Messages exchanged with one customer, newest first (incoming and outgoing, from every channel — API, Live Chat, bots, campaigns).

Parameters

phonerequiredstringCustomer number
limitinteger1–100, default 50
before_idintegerFor paging: pass next_before_id from the previous page
Request

      
Response
{
    "success": true,
    "phone": "919876543210",
    "messages": [
        {
            "id": 561,
            "message_id": "wamid.HBgM…",
            "direction": "in",
            "type": "text",
            "text": "Is it available in blue?",
            "status": "received",
            "created_at": "2026-09-24 10:25:13"
        }
    ],
    "count": 1,
    "next_before_id": 561,
    "request_id": "req_8f2c1a9d4b7e6031"
}
Messages & status

List conversations

GET /api.php?action=list_conversations

Everyone you have chatted with, most recent first, with the last message and unread count.

Parameters

limitinteger1–100, default 50
pageintegerDefault 1
Request

      
Response
{
    "success": true,
    "conversations": [
        {
            "phone": "919876543210",
            "name": "Riya Sharma",
            "last_message": "Is it available in blue?",
            "last_direction": "in",
            "last_message_at": "2026-09-24 10:25:13",
            "unread": 1,
            "total_messages": 14
        }
    ],
    "page": 1,
    "limit": 20,
    "request_id": "req_8f2c1a9d4b7e6031"
}
Media

Upload media

POST /api.php?action=upload_media

Uploads a file to WhatsApp and returns a media_id you can reuse for 30 days in send_media or template headers — faster than sending a link each time.

Parameters

filefileMultipart form field (send as multipart/form-data)
urlstringOr a public URL for us to fetch the file from
Request

      
Response
{
    "success": true,
    "media_id": "1234567890123456",
    "mime_type": "application/pdf",
    "size": 482113,
    "expires_in_days": 30,
    "request_id": "req_8f2c1a9d4b7e6031"
}
Media

Get media URL

GET /api.php?action=get_media

Returns a short-lived download URL for a media id you received in an incoming message webhook.

Parameters

media_idrequiredstring
The URL is valid for 5 minutes and must be downloaded with your WhatsApp access token in the Authorization header.
Request

      
Response
{
    "success": true,
    "media": {
        "media_id": "1234567890123456",
        "url": "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=…",
        "mime_type": "image/jpeg",
        "size": 84213,
        "sha256": "…"
    },
    "request_id": "req_8f2c1a9d4b7e6031"
}
Templates

List templates

GET /api.php?action=get_templates

All message templates on your WhatsApp account, with the variables each one needs. Alias: list_templates.

Parameters

statusstringFilter: APPROVED, PENDING, REJECTED, PAUSED
categorystringFilter: MARKETING, UTILITY, AUTHENTICATION
Request

      
Response
{
    "success": true,
    "templates": [
        {
            "id": "11",
            "name": "order_confirmed",
            "status": "APPROVED",
            "category": "UTILITY",
            "language": "en_US",
            "variables": {
                "header": [],
                "body": [
                    "1",
                    "2",
                    "3"
                ]
            },
            "components": [
                "…"
            ],
            "quality": "GREEN",
            "rejected_reason": null
        }
    ],
    "total_count": 1,
    "approved_count": 1,
    "request_id": "req_8f2c1a9d4b7e6031"
}
Templates

Get one template

GET /api.php?action=get_template

Details of a single template.

Parameters

template_namerequiredstring
languagestring
Request

      
Response
{
    "success": true,
    "template": {
        "id": "11",
        "name": "order_confirmed",
        "status": "APPROVED",
        "category": "UTILITY",
        "language": "en_US",
        "variables": {
            "body": [
                "1",
                "2",
                "3"
            ]
        },
        "components": [
            "…"
        ]
    },
    "request_id": "req_8f2c1a9d4b7e6031"
}
Templates

Create a template

POST /api.php?action=create_template

Submits a new template to Meta for review. Use the simple fields, or pass Meta’s full components array for headers with media, carousels etc.

Parameters

namerequiredstringLowercase letters, numbers, underscores
categoryrequiredstringMARKETING, UTILITY or AUTHENTICATION
languagestringDefault en_US
bodystringBody text with {{1}} variables
examplesarrayOne sample value per variable (required by Meta)
headerstringText header
footerstring
buttonsarrayMeta button objects, e.g. [{"type":"QUICK_REPLY","text":"Yes"}]
componentsarrayFull Meta components (overrides the simple fields)
Request

      
Response
{
    "success": true,
    "template": {
        "id": "1098765432109876",
        "name": "appointment_reminder",
        "status": "PENDING",
        "category": "UTILITY",
        "language": "en_US"
    },
    "request_id": "req_8f2c1a9d4b7e6031"
}
Templates

Delete a template

DELETE /api.php?action=delete_template

Deletes a template (all languages, or one version with template_id).

Parameters

template_namerequiredstring
template_idstringDelete only this language version
Request

      
Response
{
    "success": true,
    "deleted": true,
    "template_name": "appointment_reminder",
    "request_id": "req_8f2c1a9d4b7e6031"
}
Contacts (CRM)

Create a contact

POST /api.php?action=create_contact

Adds a lead to your CRM. Team routing rules (round robin, city, state…) assign it automatically.

Parameters

phonestringPhone or email is required
emailstring
namestring
companystring
statusstringnew, contacted, qualified, won, lost
tagsarray | string["vip","diwali"]
city / state / countrystring
notesstring
sourcestringDefault api
upsertbooleanUpdate the contact if the phone already exists
Returns 201. A duplicate phone returns 409 duplicate unless upsert is true.
Request

      
Response
{
    "success": true,
    "contact": {
        "id": 1520,
        "name": "Riya Sharma",
        "phone": "919876543210",
        "email": "riya@example.com",
        "company": "",
        "status": "new",
        "source": "api",
        "tags": [
            "website",
            "hot"
        ],
        "city": "Jaipur",
        "state": null,
        "country": null,
        "notes": null,
        "assigned_to": 3,
        "created_at": "2026-09-24 10:30:00",
        "updated_at": "2026-09-24 10:30:00"
    },
    "request_id": "req_8f2c1a9d4b7e6031"
}
Contacts (CRM)

List contacts

GET /api.php?action=list_contacts

Search and page through your CRM contacts.

Parameters

searchstringMatches name, phone, email, company
statusstring
tagstring
updated_sincestringDate/time, e.g. 2026-09-01
limitinteger1–200, default 50
pageinteger
Request

      
Response
{
    "success": true,
    "contacts": [
        {
            "id": 1520,
            "name": "Riya Sharma",
            "phone": "919876543210",
            "status": "new",
            "tags": [
                "website",
                "hot"
            ]
        }
    ],
    "total": 1,
    "page": 1,
    "limit": 50,
    "pages": 1,
    "request_id": "req_8f2c1a9d4b7e6031"
}
Contacts (CRM)

Get a contact

GET /api.php?action=get_contact

One contact by id or phone.

Parameters

idinteger
phonestring
Request

      
Response
{
    "success": true,
    "contact": {
        "id": 1520,
        "name": "Riya Sharma",
        "phone": "919876543210",
        "…": "…"
    },
    "request_id": "req_8f2c1a9d4b7e6031"
}
Contacts (CRM)

Update a contact

POST /api.php?action=update_contact

Change any field. Tags can be replaced, added to or removed.

Parameters

id / phonerequiredWhich contact
any contact fieldname, email, status, tags, city…
tags_modestringreplace (default), add or remove
Request

      
Response
{
    "success": true,
    "contact": {
        "id": 1520,
        "status": "qualified",
        "tags": [
            "website",
            "hot",
            "paid"
        ],
        "…": "…"
    },
    "request_id": "req_8f2c1a9d4b7e6031"
}
Contacts (CRM)

Delete a contact

DELETE /api.php?action=delete_contact

Permanently removes a contact from the CRM.

Parameters

id / phonerequired
Request

      
Response
{
    "success": true,
    "deleted": true,
    "id": 1520,
    "request_id": "req_8f2c1a9d4b7e6031"
}
Webhooks

Register a webhook

POST /api.php?action=register_webhook

We POST events to your URL in real time: incoming customer messages and delivery status updates.

Parameters

urlrequiredstringYour https endpoint
eventsarraymessage (default) and/or message.status
secretstringUsed to sign each request — see verifying signatures
labelstringA name for your reference
Request

      
Response
{
    "success": true,
    "webhook_id": 12,
    "url": "https://yourapp.com/whatsapp/webhook",
    "label": "My CRM",
    "events": [
        "message",
        "message.status"
    ],
    "secret_set": true,
    "request_id": "req_8f2c1a9d4b7e6031"
}
Webhooks

List webhooks

GET /api.php?action=list_webhooks

Your webhooks with their last delivery result.

No parameters.

Request

      
Response
{
    "success": true,
    "webhooks": [
        {
            "id": 12,
            "label": "My CRM",
            "url": "https://yourapp.com/whatsapp/webhook",
            "events": [
                "message",
                "message.status"
            ],
            "is_active": true,
            "last_called_at": "2026-09-24 10:25:13",
            "last_status": 200,
            "fail_count": 0,
            "secret_set": true
        }
    ],
    "count": 1,
    "request_id": "req_8f2c1a9d4b7e6031"
}
Webhooks

Send a test event

POST /api.php?action=test_webhook

Sends a sample message event to your webhook and tells you what your server answered.

Parameters

webhook_idrequiredinteger
Request

      
Response
{
    "success": true,
    "delivered": true,
    "http_status": 200,
    "error": null,
    "response_preview": "OK",
    "request_id": "req_8f2c1a9d4b7e6031"
}
Webhooks

Delete a webhook

DELETE /api.php?action=delete_webhook

Stops sending events to that URL.

Parameters

webhook_idrequiredinteger
Request

      
Response
{
    "success": true,
    "deleted": true,
    "webhook_id": 12,
    "request_id": "req_8f2c1a9d4b7e6031"
}

Changelog

v2 · Sep 2026 — media, interactive, location, contacts, reactions, read receipts, bulk sends, message status & history, conversations, templates create/delete, CRM contacts, message.status webhooks, rate-limit headers, stable error_codes. All v1 actions (send_message, send_text, get_templates, status, webhooks) keep working unchanged.

© 2026 Gaptix. WhatsApp is a trademark of Meta Platforms, Inc.