Skip to main content
This domain covers the full lifecycle of WhatsApp Business integration in Genuka: connecting phone numbers via Meta Embedded Signup or manually, managing message-template campaigns, sending ad-hoc messages through the proxy API, and initiating/monitoring VoIP calls using the WhatsApp Calling (FreeSWITCH-backed) feature. Webhooks from Meta are received and processed here, automatically creating customers and routing messages into the OmniBox inbox. Base URL https://api.genuka.com · Auth Authorization: Bearer <token> + X-Company: <companyId> · Getting Started

Endpoints at a glance


Connections

GET /2023-11/admin/whatsapp/connections

List all WhatsApp Business connections for the current company, ordered by is_main descending.
Success response (200 OK):
Error responses
  • 401 — Unauthenticated.

POST /2023-11/admin/whatsapp/connections

Manually register a WhatsApp Business number. The WABA must already be subscribed to the Genuka Meta app; the endpoint verifies this before creating the record. Request body
Success response (201 Created):
Error responses
  • 400 — Missing companyId header.
  • 401 — Unauthenticated.
  • 422 — Connection already exists for this phone number ID, or Genuka app is not subscribed to the WABA.
  • 502 — Could not reach Meta to verify WABA subscription.

PUT /2023-11/admin/whatsapp/connections/{connection}

Update editable fields on a connection (name overrides and identifiers only — token is not updatable here). Path parameters Request body
Success response (200 OK):
Error responses
  • 401, 403, 404, 422

DELETE /2023-11/admin/whatsapp/connections/{connection}

Delete a WhatsApp connection. Requires explicit confirmation in the request body. Path parameters Request body
Success response (200 OK):
Error responses
  • 401, 403, 404
  • 422confirmation field missing or not true.

POST /2023-11/admin/whatsapp/connections/{connection}/set-main

Designate a connection as the default (main) outbound number for the company. All other connections are unset. Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK):

GET /2023-11/admin/whatsapp/connections/{connection}/coexistence-status

Check whether the phone number is registered for both Cloud API and the WhatsApp Business App (coexistence mode). Path parameters
Success response (200 OK):
Error responses
  • 401, 404
  • 500 — Meta Graph API unreachable.

POST /2023-11/admin/whatsapp/connections/{connection}/sync-contacts

Trigger an asynchronous contacts synchronization from the WhatsApp Business App (coexistence). Results are delivered via webhooks. Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK):
Error responses
  • 401, 404, 500

POST /2023-11/admin/whatsapp/connections/{connection}/sync-history

Trigger an asynchronous message history synchronization (up to 6 months). Must be called after sync-contacts. Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK):
Error responses
  • 401, 404, 500

POST /2023-11/admin/whatsapp/connections/{connection}/sync-history-complete

Run a full coexistence sync in sequence: contacts first, then history (dispatched with a delay). The number must be in coexistence mode. Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK):
Error responses
  • 401, 404
  • 422 — Number is not in coexistence mode, or the 24-hour sync window has passed.
  • 500 — Meta API error.

OAuth / Embedded Signup

GET /2023-11/admin/whatsapp/oauth

Returns the Facebook OAuth URL to begin the Embedded Signup flow for adding a WhatsApp Business number.
Success response (200 OK):

POST /2023-11/admin/whatsapp/oauth/callback

Exchange the authorization code from Embedded Signup for a long-lived token. Registers the phone number, subscribes webhooks, and initiates coexistence sync. Request body
Success response (200 OK):
Error responses
  • 400 — Missing code or companyId.
  • 500 — Meta API error during token exchange.

GET /2023-11/whatsapp/auth/redirect

Browser redirect to the classic Facebook OAuth URL (non-Embedded Signup flow). Not used in current production.

GET /2023-11/whatsapp/auth/callback

Handles the OAuth redirect from Facebook, exchanges the code, discovers WABAs/phone numbers, and persists them. Redirects the browser to the frontend settings page.

Webhooks

GET /2023-11/whatsapp/webhook

Meta webhook verification endpoint. Meta sends a hub.challenge that this endpoint echoes back when the hub.verify_token matches. Query parameters Success response (200 OK): Plain-text challenge string.

POST /2023-11/whatsapp/webhook

Receive and process Meta webhook events (messages, statuses, template status updates, call events, coexistence sync events). Validates the X-Hub-Signature-256 header. Returns 204 immediately; processing is synchronous but fast.
Note: No Authorization or X-Company headers are needed — this endpoint is called directly by Meta. The X-Hub-Signature-256 header is used for request verification.
Incoming payload (sent by Meta)
Success response (204 No Content) Error responses
  • 403 — Invalid X-Hub-Signature-256 signature.

Packages

GET /2023-11/admin/whatsapp/packages

Returns the product configured as the WhatsApp token purchase package, with pricing variants optionally converted to the company’s currency.
Success response (200 OK): A ProductDetailResource shape — same schema as GET /2023-11/admin/products/{product} — with optional converted_price per variant and source_currency / target_currency fields.

Campaign Templates

GET /2023-11/admin/whatsapp/templates

List campaign templates. When filter[channel_type]=whatsapp (the default), templates are synced from Meta in the background (cached 30 min per company). Query parameters
Success response (200 OK): Paginated CampaignTemplateResource collection.

POST /2023-11/admin/whatsapp/templates

Create a campaign template locally and submit it to the channel provider for approval (WhatsApp requires Meta review; SMS/Email auto-approve). Accepts multipart/form-data when uploading header media. Request body (WhatsApp)
Success response (200 OK): CampaignTemplateResource — see GET single template below. Error responses
  • 401, 422
  • 4xx/5xx from Meta (provider API errors are proxied with a structured body):

POST /2023-11/admin/whatsapp/templates/bulk-delete

Delete multiple templates. Request body
Success response (200 OK):

GET /2023-11/admin/whatsapp/templates/{campaignTemplate}

Get a single template. Pass ?sync=true to refresh the approval status from Meta before returning. Path parameters Query parameters
Success response (200 OK):
Error responses
  • 401, 403, 404

PUT /2023-11/admin/whatsapp/templates/{campaignTemplate}

Update template fields. Pass ?resubmit=true to re-submit the updated template to the provider for approval. Path parameters Request body
Success response (200 OK): Updated CampaignTemplateResource (same shape as GET single template, with status_events loaded).

DELETE /2023-11/admin/whatsapp/templates/{campaignTemplate}

Soft-delete a template. Path parameters Success response (204 No Content)

POST /2023-11/admin/whatsapp/templates/{campaignTemplate}/duplicate

Duplicate a template (creates a copy with status draft). Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK): Newly created CampaignTemplateResource with "status": "draft".

POST /2023-11/admin/whatsapp/templates/{campaignTemplate}/preview

Render a preview of the template with provided variable values. Substitutes {{N}} placeholders with the supplied values. Path parameters Request body
Success response (200 OK): Rendered component text with variables substituted.

POST /2023-11/admin/whatsapp/templates/{campaignTemplate}/test

Send a test message using the template to a specified phone number. Path parameters Request body
Success response (200 OK):
Error responses
  • 401, 422
  • 502 — Meta rejected the test message.

Campaigns

GET /2023-11/admin/whatsapp/campaigns

List campaigns with filtering, sorting, and pagination. Query parameters
Success response (200 OK): Paginated CampaignResource collection.

POST /2023-11/admin/whatsapp/campaigns

Create a campaign. Set status to scheduled with a future scheduled_at to schedule, or use launch_immediately: true to start right away. Request body
Success response (200 OK): CampaignResource.
Error responses
  • 401, 422
  • 500 — Internal error (transaction rolled back).

POST /2023-11/admin/whatsapp/campaigns/bulk-delete

Delete multiple campaigns. Request body
Success response (204 No Content)

GET /2023-11/admin/whatsapp/campaigns/{campaign}

Get a single campaign with its template, customers, connection, and button-click stats. Path parameters
Success response (200 OK): CampaignResource with eager-loaded relations, delivery stats, and button_stats:

PUT /2023-11/admin/whatsapp/campaigns/{campaign}

Update campaign fields. Setting status to running immediately dispatches the send job; setting it to paused or draft pauses it. Path parameters Request body
Success response (200 OK): Updated CampaignResource (same shape as GET single campaign).

DELETE /2023-11/admin/whatsapp/campaigns/{campaign}

Hard-delete a campaign. Path parameters Success response (204 No Content)

GET /2023-11/admin/whatsapp/campaigns/{campaign}/pre-launch

Estimate the cost and recipient count before launching. Returns credit balance check. Path parameters
Success response (200 OK):

POST /2023-11/admin/whatsapp/campaigns/{campaign}/launch

Launch the campaign immediately. Schedules or dispatches the send job. Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK): Updated CampaignResource with "status": "running" (same shape as GET single campaign, including stats and button_stats if customers are loaded).
Error responses
  • 401, 404, 500

POST /2023-11/admin/whatsapp/campaigns/{campaign}/cancel-scheduled

Cancel a campaign that is in scheduled status. Returns the campaign to draft with scheduled_at cleared. Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK):
Error responses
  • 400 — Campaign is not in scheduled status, or has no scheduled job ID.

GET /2023-11/admin/whatsapp/campaigns/{campaign}/pre-retry-failed

Estimate the cost of retrying all failed messages. Path parameters Success response (200 OK):

POST /2023-11/admin/whatsapp/campaigns/{campaign}/retry-failed

Retry sending to all recipients that have status = failed. Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK): Updated CampaignResource (same shape as GET single campaign, with updated stats).

POST /2023-11/admin/whatsapp/campaigns/{campaign}/duplicate

Create a copy of the campaign (same settings, all recipients copied as pending, status set to draft). Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK): New CampaignResource with "status": "draft" and "name": "July Promo (copy)".

GET /2023-11/admin/whatsapp/campaigns/{campaign}/customers

List recipients of a campaign with their delivery pivot data. Path parameters Query parameters
Success response (200 OK): Paginated customer list.

POST /2023-11/admin/whatsapp/campaigns/{campaign}/customers/export

Export campaign recipients to CSV/XLSX asynchronously. Job is queued; the response returns an export job reference. Path parameters Query parameters Request body: None — no body required for this action endpoint.
Success response (202 Accepted): Async export queued. The download link is sent by email when ready.

GET /2023-11/admin/whatsapp/campaigns/{campaign}/customers/export/fields

List available columns for the campaign customers export. Path parameters
Success response (200 OK):

GET /2023-11/admin/whatsapp/campaigns/{campaign}/customers/{customer}

Get detailed delivery information for a single recipient, including status events and button clicks. Path parameters
Success response (200 OK):
Error responses
  • 401, 403, 404

POST /2023-11/admin/whatsapp/campaigns/{campaign}/customers/{customer}/retry

Retry sending the campaign message to a single failed recipient. Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK):
Error responses
  • 401, 404
  • 422 — Provider rejected the retry attempt.

Proxy API

The WhatsApp Proxy API lets third-party systems send WhatsApp messages on behalf of a company using scoped bearer tokens (InboxApiToken). The token is passed via the standard Authorization: Bearer header but is a different token type from the admin session token — it is issued via the proxy token management endpoints below.

POST /2023-11/whatsapp-proxy/send

Send a WhatsApp message using a proxy token. Request body
Success response (200 OK):
Error responses
  • 402 — Insufficient credits.
  • 403 — Token lacks the required scope.
  • 422 — WhatsApp connection not found.
  • 502 — Meta API rejected the message.

POST /2023-11/whatsapp-proxy/media

Upload a media file via the proxy. Returns a Meta media ID usable in subsequent send calls. Request body: multipart/form-data
Success response (200 OK):
Error responses
  • 403 — Token lacks upload_media scope.
  • 422 — Connection not found.
  • 502 — Meta upload failed.

POST /2023-11/whatsapp-proxy/typing

Send a typing indicator to a recipient. Request body
Success response (200 OK):
Error responses
  • 403 — Token lacks send_text scope.
  • 422 — Connection not found.
  • 502 — Meta API error.

Proxy Tokens (Admin)

GET /2023-11/admin/whatsapp/proxy-tokens

List all proxy API tokens for the company.
Success response (200 OK):

POST /2023-11/admin/whatsapp/proxy-tokens

Create a proxy API token. The full plain token is returned only once in the creation response. Request body
Success response (201 Created):

POST /2023-11/admin/whatsapp/proxy-tokens/{token}/revoke

Deactivate a token without deleting it (is_active set to false). Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK):
Error responses
  • 404 — Token not found or belongs to another company.

DELETE /2023-11/admin/whatsapp/proxy-tokens/{token}

Permanently delete a proxy token. Path parameters Success response (204 No Content) Error responses
  • 404 — Token not found.

Proxy Logs

GET /2023-11/admin/whatsapp/proxy-logs

List proxy API request logs for the company. Query parameters
Success response (200 OK): Paginated log collection.

Calling (WhatsApp Calls)

WhatsApp Calling is powered by a FreeSWITCH media server. The browser client uses the Verto WebRTC protocol. Call state changes are broadcast via Laravel Reverb (WebSockets).

GET /2023-11/whatsapp/calls

List calls for the company. By default returns only active calls (ringing, connecting, in_progress). Query parameters
Success response (200 OK): Array of CallResource:

POST /2023-11/whatsapp/calls

Initiate an outbound call. Requires the call.initiate permission. The user is subject to a daily outbound quota. Request body
Success response (201 Created): CallResource (same shape as the listing above).
Error responses
  • 401, 403 — Missing call.initiate permission.
  • 412 — Calling not enabled on the connection, or number not eligible.
  • 423 — Outbound paused due to unanswered calls threshold.
  • 429 — Daily outbound quota exceeded.
  • 503 — FreeSWITCH media server unavailable.

GET /2023-11/whatsapp/calls/ice-servers

Get STUN/TURN ICE server credentials (short-lived, ~5 minutes). Used by the browser WebRTC client before joining a call.
Success response (200 OK):
Error responses
  • 401
  • 403 — Missing call.listen or call.initiate permission.

GET /2023-11/whatsapp/calls/{call}

Get details of a single call. Path parameters Success response (200 OK): CallResource (same shape as the listing above).
Error responses
  • 401, 404

POST /2023-11/whatsapp/calls/{call}/terminate

End the call for all participants. Requires the call.terminate permission. Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK): Updated CallResource with terminal status.
Error responses
  • 401, 403, 404

POST /2023-11/whatsapp/calls/{call}/verto-credentials

Issue short-lived Verto WebRTC credentials for the authenticated user to join the call’s conference. Path parameters Request body: None — no body required for this action endpoint.
Success response (200 OK):
Error responses
  • 401, 404 — Call not found or user is not an active participant.

FreeSWITCH Internal Endpoints

These endpoints are protected by HTTP Basic Auth and an IP allowlist (FreeSwitchInternalAuth middleware). They are called exclusively by the FreeSWITCH media server and are not intended for external use.

POST /2023-11/whatsapp/calls/freeswitch/dialplan

XML cURL dynamic dialplan handler. FreeSWITCH POSTs the leg’s channel variables as a application/x-www-form-urlencoded body. Returns <not found/> to fall back to the static dialplan file (genuka_calls.xml) in the current phase; future phases will return dynamic XML for conference routing.
Note: This endpoint is protected by FreeSwitchInternalAuth (HTTP Basic Auth + IP allowlist). It is called exclusively by the FreeSWITCH media server — do not call it directly.
Request body (application/x-www-form-urlencoded — sent by FreeSWITCH):
Response format: text/xml — not JSON. The response body is a FreeSWITCH XML document (see example below).
Success response (200 OK, Content-Type: text/xml):

POST /2023-11/whatsapp/calls/freeswitch/directory

XML cURL directory handler. FreeSWITCH mod_verto calls this endpoint to authenticate a Verto WebRTC login before the dialplan runs. The endpoint looks up the short-lived token cached by VertoTokenService for the given login and echoes it back as the expected cleartext password. Returns <not found/> for unknown or expired sessions, causing FreeSWITCH to reject the connection.
Note: This endpoint is protected by FreeSwitchInternalAuth (HTTP Basic Auth + IP allowlist). It is called exclusively by the FreeSWITCH media server — do not call it directly.
Request body (application/x-www-form-urlencoded — sent by FreeSWITCH):
Response format: text/xml — not JSON. The response body is a FreeSWITCH XML document (see examples below).
Success response — user found (200 OK, Content-Type: text/xml):
Response — user not found / token expired (200 OK, Content-Type: text/xml):

POST /2023-11/whatsapp/calls/freeswitch/event

HTTP fallback for FS events when the ESL connection is briefly unavailable. Handles CHANNEL_HANGUP_COMPLETE to mark calls as completed. Request body (JSON): Success response (204 No Content)

POST /2023-11/whatsapp/calls/freeswitch/recording-uploaded

Acknowledgment that a call recording has been uploaded to S3. Logs the confirmation. Request body Success response (200 OK):

Miscellaneous

GET /2023-11/whatsapp

Entry-point placeholder (the index action). Currently maps to WhatsappAPIController@index which is not implemented — returns 500 if called directly.

GET /2023-11/whatsapp/login

Renders the whatsapp.login Blade view. Browser-only; not an API endpoint.

GET /whatsapp/sync/{company}

Renders the whatsapp.login Blade view for a specific company (legacy sync page). Browser-only.