API Reference
Health checks and low-level endpoints (Meta media upload, embedded-signup completion).
Low-level and operational endpoints that support the main messaging, webhook, and BYON flows.
Health checks
Two unauthenticated liveness endpoints return 200 with { "status": "ok" }. No API key is required. Use them for uptime monitoring.
GET /v1/messages/health
GET /v1/media/health{ "status": "ok" }POST /v1/media/upload/meta
Uploads a file to Meta's resumable upload API and returns a template media handle for use in template HEADER components. This is a BYON / App endpoint — it requires an ak_ App key. Pool (pk_) keys are rejected with 403 BYON_ONLY.
POST /v1/media/upload/meta
Authorization: Bearer ak_your_app_key
Content-Type: multipart/form-data| Form field | Type | Description |
|---|---|---|
file | file | Required. The media file to upload |
poolNumberId | string | Required. BYON number whose WABA credentials are used |
- Max file size: 25 MB. Larger files return
400 FILE_TOO_LARGE. - The endpoint proxies Meta's two-step resumable upload and returns Meta's handle.
- This endpoint is not rate-limited and emits no rate-limit headers.
Response
{ "handle": "h:abc123..." }Reference the returned handle in a template header's example.header_handle. See Template Management.
Errors
| Status | Code | Description |
|---|---|---|
400 | FILE_TOO_LARGE | File exceeds the 25 MB limit |
403 | BYON_ONLY | An ak_ App key is required (pool pk_ rejected) |
422 | NO_CREDENTIALS | The BYON number has no Meta access token configured |
The response body uses a nested shape: { "error": { "code": "...", "message": "..." } }. Raw errors returned by Meta are passed through unchanged.
POST /v1/apps/onboard
Completes Meta Embedded Signup. This is a public endpoint (no API key) — it is called by the hosted signup page after Meta returns an authorization code. The token is the one-time JWT minted by POST /v1/apps/token.
POST /v1/apps/onboard
Content-Type: application/json| Field | Type | Description |
|---|---|---|
token | string | Required. The single-use signup JWT |
code | string | Required. Meta authorization code from the signup dialog |
On success the server: verifies the JWT and consumes its single-use JTI, checks the App owner has an active subscription, rejects duplicate phone numbers, exchanges the code with Meta, discovers the WABA and phone details, creates the BYON pool number, and subscribes the WABA to webhooks (rolling back the number if the subscription fails).
Response
{
"numberId": "pn_abc123",
"phoneNumber": "+15551234567",
"redirectUrl": "https://yourapp.com/onboarding/complete"
}Returns 201. On the hosted page, the user is redirected to redirectUrl with ?numberId=<id>&phone=<number> appended. A number.onboarded webhook is also fired to the App's webhook URL.
Errors
Errors are returned as a flat { "error": "<message>" } body with the HTTP status — this endpoint has no machine-readable code field.
| Status | When | Example message |
|---|---|---|
400 | Missing/invalid token or code, or invalid JSON | "Missing or invalid token" |
401 | Token invalid, expired (15-min TTL), or already used | "Invalid or expired token", "Token already used" |
403 | App owner has no active subscription | "App owner subscription required to onboard numbers" |
404 | The token's App no longer exists | "App not found" |
409 | Phone number already connected | "This phone number is already connected to an App" or "This phone number is already in the pool" |