Access requirements
Send a Cogno Bearer token inAuthorization. Every operation requires active Workspace membership and integrations.manage, which the member, admin, and owner roles hold. The Workspace’s MFA policy also applies. The Workspace comes from the URL; a setup flow belongs to the user who started it.
The deployment must configure WhatsApp credentials, separate state and token encryption keys, a stable registration PIN key, an explicit Graph API version, and a public HTTPS webhook callback URL. The API and integration worker need the same configuration. DATABASE_LISTENER_URL must use a direct or session-preserving PostgreSQL endpoint. Missing configuration returns 503 with setup_not_configured.
The browser setup page also needs NEXT_PUBLIC_WHATSAPP_META_APP_ID, NEXT_PUBLIC_WHATSAPP_CONFIGURATION_ID, and NEXT_PUBLIC_WHATSAPP_GRAPH_API_VERSION at frontend build time. Match the App ID and Graph version to Core’s settings, and allow the HTTPS frontend domain in the Meta app’s Facebook Login settings. These frontend values are public; never expose the App Secret or access tokens there.
Staging test configuration
Set these four server-side environment variables only withENVIRONMENT=stg:
WHATSAPP_TEST_WORKSPACE_ID: the Cogno Workspace used for the test.WHATSAPP_TEST_MESSAGING_ACCOUNT_ID: the Meta test WhatsApp Business account ID.WHATSAPP_TEST_PHONE_NUMBER_ID: the test phone number ID, not its telephone number.WHATSAPP_TEST_ACCESS_TOKEN: the temporary Meta access token. Keep it secret; never use aNEXT_PUBLIC_variable.
whatsapp.test_connection in the staging Terraform inputs. Save the token in Secret Manager and set access_token_secret_name to its secret ID. access_token_secret_version accepts an enabled numeric version or latest; staging uses latest. The Core API and integration worker receive the same Workspace and Meta asset IDs and the same secret reference. Terraform stores the reference, not the token value. When the temporary token expires, save a new enabled secret version and redeploy both workloads through the normal release flow. Each instance resolves latest at startup; existing instances keep their current token. An existing connection also needs a new connection start to save that token; changing the secret alone does not refresh it.
The existing connection start request uses this token only for the configured Workspace and returns setup progress without requiring Embedded Signup. Other Workspaces use normal Meta sign-in. No additional endpoint or browser token field is used. The usual app, scope, expiry and phone checks, encrypted credential storage and setup worker still apply. A temporary token must be refreshed in the server configuration before reconnecting after expiry.
Leave all four unset to use normal signup. Partial configuration, or test credentials configured outside staging, returns 503 setup_not_configured. Existing backend and frontend signup configuration remains required.
Endpoints
The base path is/api/v1/whatsapp/workspaces/{workspace_id}/connection-flows.
The authorization request accepts exactly these fields:
The API checks the token and the selected number’s account membership before saving the authorization. The code is exchanged during the authorization request. Tokens are encrypted in storage and are never returned in progress responses or put in job arguments.
Request sequence
1
Start a flow
Send
POST to the base path. Retain the returned state and progress.flow_id. The authorization state expires ten minutes after starting; the setup flow expires after one day.2
Submit Meta authorization
Complete Meta authorization and submit its code and selected account and phone IDs to
/authorization, together with the retained state. A successful acceptance returns configuring; setup continues in the background.3
Read progress
Request
GET /{flow_id} until setup completes or requires action. Repeating the same accepted authorization returns its saved progress without exchanging the code again.Progress and recovery
Progress containsflow_id, status, expires_at, connection_id, phone_number_id, and last_error_code. Every setup response uses Cache-Control: no-store.
The worker retries explicitly transient setup failures, up to six attempts. An exhausted transient failure moves the flow to
action_required. A saved valid authorization can be resumed after correcting the problem. An interrupted code exchange, invalid authorization, permission failure, or account mismatch requires fresh authorization.
Errors
Expected failures useapplication/problem+json with type, title, status, and a stable code. Invalid requests return a generic error without echoing the submitted code or state.
Receive webhooks
Set the Meta app’s callback URL andWHATSAPP_WEBHOOK_CALLBACK_URL to https://[your-api-host]/api/v1/whatsapp/webhook. Configure WHATSAPP_WEBHOOK_VERIFY_TOKEN with a dedicated verification string, then enter the same string in Meta’s webhook settings. POST verification uses WHATSAPP_META_APP_SECRET and WHATSAPP_META_APP_ID from the deployment configuration; webhook requests do not use Cogno Bearer tokens.
Subscribe to messages for incoming messages and delivery/read statuses. For group metadata notifications, also subscribe to group_lifecycle_update, group_participants_update, group_settings_update, and group_status_update. See Meta’s webhook setup and group webhook reference.
The receiver accepts at most 3 MiB per request. It matches the app, WhatsApp Business Account, and current primary phone number to an active, unexpired Workspace authorization. Unknown or disconnected targets and unrelated subscription fields are acknowledged without saving. A connection still being configured returns
503 so Meta can retry after setup completes.
Accepted records are committed together. Repeated deliveries are deduplicated. Message text, sender identity, reply references, and available media metadata are stored; attachments are not downloaded. Delivery statuses and group changes are saved as notifications rather than conversation messages. These records are Workspace knowledge and are not sent to an external index.
Senders are identified by Meta’s business-scoped user ID (BSUID). One-to-one conversations use the other person’s BSUID; group conversations use group_id, so different participants stay in the same conversation. Contact names are matched by contacts[].user_id. Sender phone numbers (from and wa_id) are optional metadata and never determine identity. The receiving business’s metadata.phone_number_id remains required to resolve the connection. Identity-change system messages use the BSUID in system.user_id when from_user_id is absent; their previous IDs are retained in the message details, without merging conversation history. See Meta’s BSUID reference.
Background message processing is enabled by default (WHATSAPP_SEMANTIC_REDUCTION_ENABLED=true). Set it to false in the API to retain messages without scheduling further processing. Each newly accepted normal message and its processing job are committed together. The worker converts the saved message into a structured conversation event and a readable representation without calling Meta or an LLM. Reprocessing the same message does not create a second event. The shared semantic-reduction job retries failures up to five times after the initial attempt. Delivery/read statuses, group notifications, and system messages do not queue this processing. Previously saved messages are not automatically reprocessed, including when Meta redelivers them.
Text-bearing events reach the existing Attention Gate, which decides whether to act now, later, or ignore the conversation, and which active Projects it concerns. WhatsApp uses the Workspace’s connected account; it has no Project source filters. Conversation identity includes the connection and receiving business phone, so matching BSUIDs or group IDs on another connection do not mix. The Gate and the resulting run can read bounded retained history, including a quoted message when available. External sender names do not establish Workspace member identity. Tasks filed from this workflow carry the source family whatsapp_thread and the source event ID. Task execution uses the existing Environment and agent setup; receiving a message does not guarantee a new Task.