AR Inbox API docs

Developer reference

AppRinger WA API

Send WhatsApp messages, manage templates, and embed the AR Inbox UI inside your CRM. All endpoints live under https://wa.appringer.co.in/api/v1 and authenticate with a Sanctum API key (issued from Settings → Integration → API keys).

Base URL
https://wa.appringer.co.in/api/v1
Auth header (either works)
  • Authorization: Bearer <api-key>
  • X-API-Key: <api-key>

Getting started

  1. Sign in to AR Inbox and open Settings → Integration → API keys.
  2. Create a key with the abilities you need (e.g. messages:send, templates:read). The plaintext token is shown once — copy it immediately.
  3. Make a sanity call to GET /me to confirm the key + abilities.
  4. Send your first message with POST /messages/template.

Authentication

Every request must carry an API key in either of these headers (use whichever your HTTP client prefers — they're equivalent):

Authorization: Bearer wabt_xxxxxxxxxxxxxxxxxxxxxxxx
X-API-Key: wabt_xxxxxxxxxxxxxxxxxxxxxxxx

Each key is scoped to a single merchant and a fixed set of abilities (Sanctum scopes). Calling an endpoint with a key that's missing the required ability returns 403 forbidden. Keys can be revoked at any time from the integration panel; revocation is immediate.

Response envelope

Every /api/v1/* response is wrapped in a consistent envelope. Branch on code (numeric, mirrors the HTTP status) or the HTTP status itself — both will always agree.

Success (2xx)
{
  "code": 200,
  "data": { … },
  "message": "OK"
}
Error (≥400)
{
  "code": 422,
  "data": null,
  "error": "validation_failed",
  "message": "The body field is required.",
  "errors": {
    "body": ["The body field is required."]
  }
}

On errors, data is always null and a top-level error slug identifies the failure class. Field-level validation errors are surfaced as a top-level errors map (Laravel-conventional shape). Subscription-blocked responses additionally include a pay_now URL.

Error codes

The error slug returned in the envelope identifies the failure cleanly without parsing the prose message. Common values across endpoints:

HTTP Error slug When
400 bad_request Malformed request (e.g. invalid JSON body).
401 unauthenticated Missing, malformed, or revoked API key.
403 forbidden Key is valid but missing the required ability for this endpoint.
404 not_found The referenced resource (template id, etc.) does not exist on this merchant.
409 conflict The mutation conflicts with current state (e.g. duplicate template name+language).
422 validation_failed Request body / query failed validation. Includes errors map.
422 invalid_variables Template variables don't match the template definition.
402 subscription_blocked Merchant's annual platform fee is unpaid. Response includes pay_now.
429 too_many_requests Rate limit exceeded; retry with backoff.
500 server_error Unhandled exception inside AR Inbox. Logged with a correlation id; safe to retry.

A handful of domain-specific errors (SessionWindowClosedException, WabaNotConnectedException, InsufficientWalletBalanceException) surface their class basename as error rather than a slug — these are documented inline per endpoint below.

Outbound Webhooks

Configure real-time webhooks under Settings → Developer & Webhook Settings to receive instant HTTP POST callbacks when message statuses update or inbound button replies occur.

Supported Event Types

Event Description
msg_sent Fired when an outbound message is queued and dispatched to Meta.
msg_delivered Fired when Meta confirms message delivery to the recipient's phone.
msg_read Fired when the recipient opens and reads the WhatsApp message.
msg_failed Fired when message delivery fails due to invalid recipient or Meta error.
msg_skipped Fired when a message is skipped because the recipient's WhatsApp availability probability score falls below the configured threshold.
button_reply Fired when an inbound quick-reply or button response is received.

HMAC Signature Verification

When a secret is configured, every HTTP POST request contains the X-AppRinger-Signature header computed via HMAC SHA-256 over the raw JSON payload:

$signature = hash_hmac('sha256', $rawBody, $webhookSecret);

Sample Payloads by Event

{
  "event": "msg_skipped",
  "msg_id": "MSG_CUSTOM_001",
  "camp_id": "CAMP_AUGUST_01",
  "client_reference": "order-1234",
  "wa_message_id": null,
  "status": "skipped_low_probability",
  "recipient": "+919876543210",
  "template_name": "welcome_alert",
  "wa_probability_score": {
    "phone": "+919876543210",
    "delivery_probability": 15.4,
    "read_probability": 8.2,
    "risk_level": "high",
    "data_points": 142
  },
  "timestamp": "2026-08-01T08:50:00+00:00"
}
{
  "event": "msg_sent",
  "msg_id": "MSG_CUSTOM_001",
  "camp_id": "CAMP_AUGUST_01",
  "client_reference": "order-1234",
  "wa_message_id": "wamid.HBgMOTE4MTQzOTU2NDM4...",
  "status": "sent",
  "recipient": "+919876543210",
  "timestamp": "2026-08-01T08:50:00+00:00"
}
{
  "event": "msg_delivered",
  "msg_id": "MSG_CUSTOM_001",
  "camp_id": "CAMP_AUGUST_01",
  "client_reference": "order-1234",
  "wa_message_id": "wamid.HBgMOTE4MTQzOTU2NDM4...",
  "status": "delivered",
  "recipient": "+919876543210",
  "timestamp": "2026-08-01T08:50:02+00:00"
}
{
  "event": "msg_read",
  "msg_id": "MSG_CUSTOM_001",
  "camp_id": "CAMP_AUGUST_01",
  "client_reference": "order-1234",
  "wa_message_id": "wamid.HBgMOTE4MTQzOTU2NDM4...",
  "status": "read",
  "recipient": "+919876543210",
  "timestamp": "2026-08-01T08:51:15+00:00"
}
{
  "event": "msg_failed",
  "msg_id": "MSG_CUSTOM_001",
  "camp_id": "CAMP_AUGUST_01",
  "client_reference": "order-1234",
  "wa_message_id": "wamid.HBgMOTE4MTQzOTU2NDM4...",
  "status": "failed",
  "recipient": "+919876543210",
  "error_code": "131026",
  "error_title": "Undeliverable",
  "error_message": "Unable to deliver message to recipient number",
  "timestamp": "2026-08-01T08:50:05+00:00"
}
{
  "event": "button_reply",
  "wa_message_id": "wamid.HBgMOTE4MTQzOTU2NDM5...",
  "from": "+919876543210",
  "recipient": "+919717146603",
  "body": "Confirm Order",
  "button_reply": {
    "title": "Confirm Order",
    "id": "BTN_CONFIRM_123",
    "payload": "BTN_CONFIRM_123"
  },
  "timestamp": "2026-08-01T08:52:00+00:00"
}
GET /me #

Sanity-check the API key

Returns the owning user, their merchant account and the abilities granted to the token. Hit this first after issuing a key to confirm credentials are wired up correctly.

cURL
curl -X GET 'https://wa.appringer.co.in/api/v1/me' \
  -H 'X-API-Key: YOUR_API_KEY'

Response · 200

200 OK
{
    "code": 200,
    "data": {
        "user": {
            "id": 1,
            "name": "Riya Singh",
            "email": "riya@acme.test",
            "role": "merchant_admin"
        },
        "merchant": {
            "id": 1,
            "name": "Acme Pvt Ltd",
            "slug": "acme"
        },
        "token": {
            "name": "crm-prod",
            "abilities": [
                "messages:send",
                "templates:read"
            ]
        }
    },
    "message": "OK"
}

Errors

HTTP Error slug When
401 unauthenticated Missing, malformed, or revoked API key.
GET /wallet/balance ability: wallet:read #

Check the prepaid balance

Returns the current wallet balance, the configured low-balance threshold, and the per-message rates this merchant pays. Useful for surfacing a top-up nag inside your own dashboard before a send fails with InsufficientWalletBalanceException.

cURL
curl -X GET 'https://wa.appringer.co.in/api/v1/wallet/balance' \
  -H 'X-API-Key: YOUR_API_KEY'

Response · 200

200 OK
{
    "code": 200,
    "data": {
        "merchant": {
            "id": 1,
            "slug": "acme"
        },
        "currency": "INR",
        "balance": "1000.00",
        "low_balance_threshold": "500.00",
        "is_low_balance": false,
        "rates": {
            "session": "0.50",
            "utility": "0.60",
            "marketing": "1.20",
            "authentication": "0.40",
            "text": "0.50",
            "template": "0.60"
        }
    },
    "message": "OK"
}

Errors

HTTP Error slug When
401 unauthenticated Missing or invalid API key.
403 forbidden Key is missing the wallet:read ability.
402 subscription_blocked Annual platform fee unpaid. Response includes pay_now URL.
POST /messages/text ability: messages:send #

Send a session (free-form) text message

Sends a plaintext WhatsApp message. Only allowed inside the 24-hour customer service window (i.e. the recipient must have messaged you in the last 24 hours). Use POST /messages/template to re-engage outside the window.

Request body

Field Type Description
to
required
string E.164 recipient phone, no leading +. Required unless conversation_id is supplied. 5–32 chars.
body
required
string Message text. 1–4096 chars.
conversation_id
optional
integer AR Inbox conversation id. When set, the recipient + phone are inferred from the conversation and to can be omitted.
phone_number_id
optional
integer AR Inbox phone-number row id. Send from a specific number when the merchant has multiple connected numbers. Defaults to the merchant's default number.
client_reference
optional
string Your idempotency key / order id. Echoed back on the response and on every status webhook. ≤64 chars.
msg_id
optional
string Your custom message ID. Echoed back on status responses, status webhooks, and queryable via GET /messages/status/{msgId}. ≤128 chars.
camp_id
optional
string Campaign identifier for tracking campaign performance across webhooks. ≤128 chars.
cURL
curl -X POST 'https://wa.appringer.co.in/api/v1/messages/text' \
  -H 'X-API-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "to": "919876543210",
    "body": "Hi, your order #1234 has shipped.",
    "client_reference": "order-1234"
}'

Response · 202

202 Accepted
{
    "code": 202,
    "data": {
        "id": 42,
        "status": "queued",
        "client_reference": "order-1234",
        "wa_message_id": null,
        "billed_amount": "0.5000",
        "currency": "INR"
    },
    "message": "Accepted"
}

status starts at queued and progresses to sent / delivered / read as Meta acknowledges. Occasionally Meta acks within the same request and you'll see sent already in this response. billed_amount is a decimal string (4 d.p.); wa_message_id is filled once Meta returns it (poll id if you need it synchronously).

Errors

HTTP Error slug When
401 unauthenticated Missing or invalid API key.
403 forbidden Key is missing the messages:send ability.
422 validation_failed Required field missing or malformed. Response includes errors: { field: [messages] }.
422 SessionWindowClosedException Recipient has not messaged you in the last 24h. Send a template instead.
402 InsufficientWalletBalanceException Wallet balance is below the cost of this send. Top up at the URL in pay_now.
409 WabaNotConnectedException Merchant has no connected WhatsApp number. Complete the registration wizard in the AR Inbox dashboard.
402 subscription_blocked Annual platform fee unpaid.
POST /messages/template ability: messages:send #

Send an approved template message

Send one of your approved templates. Use this for any first-touch / re-engagement send outside the 24-hour session window — order confirmations, shipping updates, marketing nudges, OTPs. Pass either template_id (preferred — copy it from WhatsApp settings → Templates) or the template_name+language pair.

Authentication (OTP) Templates:
For authentication templates with a Copy Code or One-Tap Autofill button, you must supply the OTP code twice in the API request: once for the message body and once for the button. You can do this easily using the simplified variables and button_variables fields, or via raw components.

Example using variables:

{
  "to": "919876543210",
  "template_name": "otp_verification",
  "language": "en_US",
  "variables": {"1": "123456"},
  "button_variables": ["123456"]
}

Request body

Field Type Description
to
required
string E.164 recipient phone, no leading +. Required unless conversation_id is supplied.
template_id
conditional
integer AR Inbox template id. Required unless template_name + language are supplied. Copy it from the API id chip next to each template in the dashboard.
template_name
conditional
string Template name as registered with Meta. Required when template_id is omitted.
language
conditional
string BCP-47 language tag (e.g. en_US). Required when template_id is omitted.
variables
optional
object Positional map for {{1}}, {{2}}… in the body. We build Meta's components for you. Keys can be "1", "2"… or named (when your template defines named params).
header_variables
optional
array Values for header placeholders, in order.
button_variables
optional
array Values for URL-button or OTP/Authentication button (Copy Code / One-Tap) placeholders, in order.
components
optional
array Raw Meta-shape components array. Power-user escape hatch — wins over variables if both are sent. Use this when a header carries a media asset.
conversation_id
optional
integer AR Inbox conversation id. Optional alternative to to.
phone_number_id
optional
integer Send from a specific number. Defaults to the merchant's default.
client_reference
optional
string Your idempotency key / order id. Echoed back on the response and on every status webhook.
msg_id
optional
string Your custom message ID. Echoed back on status responses, status webhooks, and queryable via GET /messages/status/{msgId}. ≤128 chars.
camp_id
optional
string Campaign identifier for tracking campaign performance across webhooks. ≤128 chars.
cURL
curl -X POST 'https://wa.appringer.co.in/api/v1/messages/template' \
  -H 'X-API-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "to": "919876543210",
    "template_id": 42,
    "variables": {
        "1": "Riya",
        "2": "A-12"
    },
    "client_reference": "order-1234"
}'

Response · 202

202 Accepted
{
    "code": 202,
    "data": {
        "id": 43,
        "status": "sent",
        "client_reference": "order-1234",
        "wa_message_id": "wamid.HBgMOTE4MTQzOTU2NDM4FQIAERgSMUQ3...",
        "billed_amount": "0.6000",
        "currency": "INR",
        "template_name": "order_confirmation"
    },
    "message": "Accepted"
}

Identical envelope to /messages/text plus a template_name field for traceability. status is usually queued; if Meta acks before this response returns you may see sent directly. wa_message_id is filled once Meta returns the WAMID.

Errors

HTTP Error slug When
401 unauthenticated Missing or invalid API key.
403 forbidden Key missing messages:send.
404 not_found Template id / name+language doesn't match any template on this merchant. Run GET /templates to list what's available.
422 validation_failed Required field missing or malformed.
422 invalid_variables The variables map doesn't match what the template definition expects.
402 InsufficientWalletBalanceException Wallet too low for the per-template rate.
409 WabaNotConnectedException No connected WhatsApp number on this merchant.
402 subscription_blocked Annual platform fee unpaid.
POST /messages/bulk-template ability: messages:send #

Send a template message in bulk

Send an approved template to multiple recipients in one request. Useful for broadcasts and large campaigns.

Request body

Field Type Description
template_id
optional
integer AR Inbox template id.
template_name
optional
string Template name as registered with Meta.
language
optional
string BCP-47 language tag.
phone_number_id
optional
integer Send from a specific number. Defaults to the merchant's default.
recipients
required
array List of recipient objects (up to 10000).
recipients[].to
required
string E.164 recipient phone.
recipients[].variables
optional
object Variables for this recipient.
cURL
curl -X POST 'https://wa.appringer.co.in/api/v1/messages/bulk-template' \
  -H 'X-API-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "template_id": 42,
    "recipients": [
        {
            "to": "919876543210",
            "variables": { "1": "Riya" },
            "client_reference": "order-1"
        }
    ]
}'

Response · 202

202 Accepted
{
    "message": "Bulk message queued successfully.",
    "queued_count": 1
}

Errors

HTTP Error slug When
401 unauthenticated Missing or invalid API key.
403 forbidden Key missing messages:send ability.
422 validation_failed Required field missing or malformed.
GET /messages/status/{msgId} ability: messages:send #

Check delivery status by msg_id

Query the current delivery status of a message using your custom msg_id, Meta's wa_message_id, or client_reference. Returns delivery timestamps and error details if the send failed.

cURL
curl -X GET 'https://wa.appringer.co.in/api/v1/messages/status/MSG_12345' \
  -H 'X-API-Key: YOUR_API_KEY'

Response · 200

200 OK
{
    "code": 200,
    "data": {
        "id": 42,
        "msg_id": "MSG_12345",
        "camp_id": "CAMP_6789",
        "client_reference": "order-1234",
        "wa_message_id": "wamid.HBgMOTE4MTQzOTU2NDM4...",
        "recipient": "+919876543210",
        "status": "delivered",
        "sent_at": "2026-08-01T08:50:00+00:00",
        "delivered_at": "2026-08-01T08:50:02+00:00",
        "read_at": null,
        "failed_at": null,
        "error_code": null,
        "error_title": null,
        "error_message": null,
        "billed_amount": "0.5000",
        "currency": "INR"
    },
    "message": "OK"
}

Errors

HTTP Error slug When
401 unauthenticated Missing or invalid API key.
403 forbidden Key missing messages:send ability.
404 not_found Message with the given msg_id not found.
GET /phone-numbers ability: messages:send #

List your WhatsApp senders

Discovery endpoint for the phone_number_id you can pass to POST /messages/text and POST /messages/template when routing through a specific sender on a multi-line merchant. Omit phone_number_id on the send endpoints and we'll use the row flagged is_default: true here.

Query parameters

Field Type Description
status
optional
string Filter by phone state. One of connected (default), pending, disconnected, or all. Only connected rows are valid as phone_number_id on the send endpoints; ?status=all is for auditing why a number disappeared.
cURL
curl -X GET 'https://wa.appringer.co.in/api/v1/phone-numbers' \
  -H 'X-API-Key: YOUR_API_KEY'

Response · 200

200 OK
{
    "code": 200,
    "data": {
        "data": [
            {
                "id": 7,
                "display_phone_number": "+91 80 5555 5555",
                "verified_name": "Acme Pvt Ltd",
                "status": "connected",
                "is_default": true,
                "quality_rating": "GREEN"
            },
            {
                "id": 12,
                "display_phone_number": "+91 80 5555 7777",
                "verified_name": "Acme Support",
                "status": "connected",
                "is_default": false,
                "quality_rating": "GREEN"
            }
        ],
        "meta": {
            "count": 2,
            "status": "connected"
        }
    },
    "message": "OK"
}

Rows are sorted with the default-flagged number first, then by id — same order as the picker on the dashboard. id is the value to pass as phone_number_id on the send endpoints; display_phone_number is for showing in your own UI.

Errors

HTTP Error slug When
401 unauthenticated Missing or invalid API key.
403 forbidden Key is missing the messages:send ability.
GET /templates ability: templates:read #

List your templates

Returns the catalog of templates registered on the merchant. By default a slim summary per row; pass ?detailed=true to also receive the full Meta-shape components + example blobs.

Tip: the API id chip next to each template in WhatsApp settings → Templates is the same id returned here — no need to hit this endpoint just to look up an id.

Query parameters

Field Type Description
category
optional
string Filter by UTILITY, MARKETING, or AUTHENTICATION.
status
optional
string Filter by pending, approved, rejected, paused, disabled, or deleted.
per_page
optional
integer Page size, 1–200. Default 50.
detailed
optional
boolean Include full components + example blobs. Default false.
cURL
curl -X GET 'https://wa.appringer.co.in/api/v1/templates?status=approved&category=UTILITY' \
  -H 'X-API-Key: YOUR_API_KEY'

Response · 200

200 OK
{
    "code": 200,
    "data": {
        "data": [
            {
                "id": 3,
                "name": "new_lead_collected",
                "language": "en",
                "category": "UTILITY",
                "status": "approved",
                "meta_template_id": "867792625617937",
                "approved_at": "2026-05-20T08:34:00+00:00",
                "body_preview": "🛎 New Lead Collected\nCustomer: *{{1}}*…",
                "variables_count": 4,
                "buttons_count": 0,
                "has_header": false,
                "has_footer": false
            }
        ],
        "meta": {
            "page": 1,
            "per_page": 50,
            "total": 1,
            "total_pages": 1
        }
    },
    "message": "OK"
}

Errors

HTTP Error slug When
401 unauthenticated Missing or invalid API key.
403 forbidden Key missing templates:read.
422 validation_failed Unknown category or status value, or per_page out of range.
POST /templates ability: templates:write #

Register a new template for Meta review

Submits a draft template to Meta for review. Lands locally in pending status; Meta typically returns an approval within minutes and the row auto-flips to approved via webhook. Once approved, send it with POST /messages/template.

Request body

Field Type Description
name
required
string Snake_case template id, max 128 chars. Must match /^[a-z0-9_]+$/i. Must be unique per language.
language
required
string BCP-47 language tag, e.g. en_US, hi, mr.
category
required
string One of UTILITY (transactional), MARKETING (promotional), AUTHENTICATION (OTP).
components
required
array Meta-shape components array. At minimum a BODY component with text. Use {{1}}, {{2}}… for placeholders.
example
optional
object Sample values Meta uses while reviewing. Required for templates with placeholders, e.g. { "body_text": [["Riya", "A-12"]] }.
cURL
curl -X POST 'https://wa.appringer.co.in/api/v1/templates' \
  -H 'X-API-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "order_confirmation",
    "language": "en_US",
    "category": "UTILITY",
    "components": [
        { "type": "BODY", "text": "Hi {{1}}, your order {{2}} is confirmed." }
    ],
    "example": { "body_text": [["Riya", "A-12"]] }
}'

Response · 201

201 Created
{
    "code": 201,
    "data": {
        "id": 5,
        "name": "order_confirmation",
        "language": "en_US",
        "category": "UTILITY",
        "status": "pending",
        "meta_template_id": null,
        "approved_at": null,
        "components": [
            {
                "type": "BODY",
                "text": "Hi {{1}}, your order {{2}} is confirmed."
            }
        ],
        "example": {
            "body_text": [
                [
                    "Riya",
                    "A-12"
                ]
            ]
        }
    },
    "message": "Created"
}

Errors

HTTP Error slug When
401 unauthenticated Missing or invalid API key.
403 forbidden Key missing templates:write.
422 validation_failed Malformed components, missing example for a placeholder template, etc.
409 conflict A template with the same name+language already exists on this merchant.
DELETE /templates/{id} ability: templates:write #

Delete a template

Deletes a template. Note that this only removes the template from AR Inbox; you must still delete it in the Meta Business Manager.

cURL
curl -X DELETE 'https://wa.appringer.co.in/api/v1/templates/42' \
  -H 'X-API-Key: YOUR_API_KEY'

Response · 200

200 OK
{
    "message": "Template deleted successfully."
}

Errors

HTTP Error slug When
401 unauthenticated Missing or invalid API key.
403 forbidden Key missing templates:write.
404 not_found Template not found for this merchant.
POST /iframe-tokens ability: iframe:mint #

Mint a JWT for embedded SSO (BETA)

BETA / Testing Feature: Server-to-server mint of a short-lived JWT for Iframe SSO embedding inside partner CRMs. Use the returned embed_url as an iframe src to drop the AR Inbox UI inside your CRM with the targeted user already signed in. With auto_provision: true, the user is created on-the-fly if they don't exist yet.

Request body

Field Type Description
email
optional
string Target user's email. Required unless user_id is supplied.
user_id
optional
integer AR Inbox user id. Required unless email is supplied.
ttl_seconds
optional
integer Token lifetime, 60–86400 (24h). Default 300 (5 min).
redirect_to
optional
string Path inside AR Inbox to land on. Must start with /. Defaults to /inbox.
auto_provision
optional
boolean Create the user if not found. Requires email + name + role.
role
optional
string When auto-provisioning: agent or manager.
name
optional
string When auto-provisioning: display name, max 120 chars.
features
optional
array When auto-provisioning: subset of ["inbox", "tasks"] to grant.
cURL
curl -X POST 'https://wa.appringer.co.in/api/v1/iframe-tokens' \
  -H 'X-API-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "email": "agent@acme.com",
    "ttl_seconds": 300,
    "redirect_to": "/inbox",
    "auto_provision": true,
    "role": "agent",
    "features": ["inbox", "tasks"]
}'

Response · 200

200 OK
{
    "code": 200,
    "data": {
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIsImV4cCI6MTczMjAwMDAwMH0.signature",
        "expires_at": "2026-05-20T14:00:00+00:00",
        "embed_url": "https://app.example.com/embed?token=eyJ0eXAi...",
        "ttl_seconds": 300,
        "user": {
            "id": 2,
            "email": "agent@acme.com",
            "name": "Agent Two",
            "role": "agent"
        },
        "provisioned": false
    },
    "message": "OK"
}

Errors

HTTP Error slug When
401 unauthenticated Missing or invalid API key.
403 forbidden Key missing iframe:mint or not merchant-scoped.
404 not_found User not found. Pass auto_provision: true + name + role to create them on the fly.
422 provision_failed Auto-provision validation failed. Response includes errors map.
422 user_inactive Target user is disabled.
422 merchant_missing API key's merchant row is missing (rare; usually a deleted merchant).
© 2026 AppRinger WA. WhatsApp is a trademark of Meta Platforms, Inc. Need help? hello@appringer.com