Getting Started

Authentication

All API requests require a Bearer token in the Authorization header:

Authorization: Bearer <YOUR_API_KEY>

API keys are scoped to an organization. You receive one when completing the onboarding flow (see the Onboarding Links guide).

Error responses for invalid or missing authentication:


Core Concepts

Data Model

Organization
├── API Keys
├── Onboarding Links
├── Shared Inbox Links
├── Outgoing Webhooks
└── WABAs (WhatsApp Business Accounts)
    └── Phone Numbers
        └── Conversations
            └── Messages

IDs

The API uses two kinds of IDs:

ID Type Format Example
Internal IDs UUID v4 550e8400-e29b-41d4-a716-446655440000
Meta IDs Numeric string 123456789012345

Most endpoints use internal UUIDs. Meta IDs appear in webhook payloads and when interfacing with Meta's Graph API.


Quick Start

1. Connect a WhatsApp Number

Create an onboarding link and send it to your end-user:

curl -X POST https://api.example.com/v1/onboarding-links \
  -H "Authorization: Bearer sk_org_..." \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme Corp", "redirectUrl": "https://myapp.com/callback"}'

Send the hostedUrl from the response to your end-user. They complete Meta's Embedded Signup in the browser. See the Onboarding Links guide for the full flow.

2. Check Phone Health

Before sending production traffic, fetch the phone health snapshot:

curl https://api.example.com/v1/phones/{phoneId}/health \
  -H "Authorization: Bearer sk_org_..."

Look at data.capabilities.canReceiveMessages:

This endpoint also triggers an asynchronous resync against Meta in the background. If the local state was stale, a subsequent call will reflect the refreshed values.

3. Send a Message

Before sending outbound traffic, confirm data.capabilities.canSendMessages is true:

curl -X POST https://api.example.com/v1/phones/{phoneId}/messages \
  -H "Authorization: Bearer sk_org_..." \
  -H "Content-Type: application/json" \
  -d '{"type": "text", "to": "5491155551234", "text": "Hello!"}'

See the Sending Messages guide for all message types.

4. Optionally Expose a Shared Inbox

If you want an external user to work inside the inbox UI without giving them your org API key, create a shared inbox link:

curl -X POST https://api.example.com/v1/shared-inbox-links \
  -H "Authorization: Bearer sk_org_..." \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumberId": "660e8400-e29b-41d4-a716-446655440001",
    "name": "Support access",
    "permissions": {
      "readInbox": true,
      "readDetails": true,
      "markRead": true,
      "sendText": true,
      "sendMedia": true,
      "sendTemplates": true,
      "sendAdvanced": false
    }
  }'

Send the publicUrl from the response to the external user. See the Shared Inbox Links guide for permissions, expiry, rotation, and revoke flows.

5. Receive Messages via Webhooks

Register a webhook to get notified of incoming messages and status updates:

curl -X POST https://api.example.com/v1/outgoing-webhooks \
  -H "Authorization: Bearer sk_org_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/whatsapp",
    "events": ["message.received", "message.sent"],
    "secret": "whsec_your_secret_key"
  }'

See the Webhooks guide for payload formats and signature verification.


Phone Readiness

The platform stores two related but different fields for each phone number:

Field Meaning
isRegistered The phone has been registered with WhatsApp / Cloud API
capabilities.canReceiveMessages The phone is ready for inbound traffic with the current app subscription and no blocking health issues
capabilities.canSendMessages The phone is healthy enough for outbound messaging
capabilities.canSendTemplates The phone is healthy enough for outbound template messaging

Use the capability that matches your integration. For inbound-only flows, canReceiveMessages is usually the right operational flag.


Response Format

All responses follow a consistent envelope:

Success (single resource):

{
  "data": { ... }
}

Success (list):

{
  "data": [ ... ],
  "meta": {
    "pagination": {
      "page": 1,
      "limit": 50,
      "total": 120,
      "hasMore": true
    }
  }
}

Error:

{
  "error": {
    "message": "Resource not found",
    "code": "NOT_FOUND"
  }
}

Error Codes

Code HTTP Status Description
VALIDATION_ERROR 400 Invalid request body or parameters
UNAUTHORIZED 401 Missing or invalid API key
FORBIDDEN 403 API key doesn't have access
NOT_FOUND 404 Resource not found
INTERNAL_ERROR 500 Unexpected server error