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.
200 OK):
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
201 Created):
400— MissingcompanyIdheader.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
200 OK):
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
200 OK):
401,403,404422—confirmationfield missing or nottrue.
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.
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
200 OK):
401,404500— 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.
200 OK):
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.
200 OK):
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.
200 OK):
401,404422— 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.
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
200 OK):
400— MissingcodeorcompanyId.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: NoIncoming payload (sent by Meta)AuthorizationorX-Companyheaders are needed — this endpoint is called directly by Meta. TheX-Hub-Signature-256header is used for request verification.
204 No Content)
Error responses
403— InvalidX-Hub-Signature-256signature.
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.
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
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)
200 OK): CampaignTemplateResource — see GET single template below.
Error responses
401,4224xx/5xxfrom Meta (provider API errors are proxied with a structured body):
POST /2023-11/admin/whatsapp/templates/bulk-delete
Delete multiple templates.
Request body
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
200 OK):
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
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.
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
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
200 OK):
401,422502— Meta rejected the test message.
Campaigns
GET /2023-11/admin/whatsapp/campaigns
List campaigns with filtering, sorting, and pagination.
Query parameters
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
200 OK): CampaignResource.
401,422500— Internal error (transaction rolled back).
POST /2023-11/admin/whatsapp/campaigns/bulk-delete
Delete multiple campaigns.
Request body
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
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
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
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.
200 OK): Updated CampaignResource with "status": "running" (same shape as GET single campaign, including stats and button_stats if customers are loaded).
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.
200 OK):
400— Campaign is not inscheduledstatus, 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.
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.
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
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.
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
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
200 OK):
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.
200 OK):
401,404422— 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
200 OK):
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
200 OK):
403— Token lacksupload_mediascope.422— Connection not found.502— Meta upload failed.
POST /2023-11/whatsapp-proxy/typing
Send a typing indicator to a recipient.
Request body
200 OK):
403— Token lackssend_textscope.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.
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
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.
200 OK):
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
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
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
201 Created): CallResource (same shape as the listing above).
401,403— Missingcall.initiatepermission.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.
200 OK):
401403— Missingcall.listenorcall.initiatepermission.
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).
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.
200 OK): Updated CallResource with terminal status.
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.
200 OK):
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).
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).
200 OK, Content-Type: text/xml):
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.