Best practices
Build a reliable WhatsApp integration against the durable contract.
- Use a stable idempotency key for every logical send, and reuse it only when retrying that same request.
- Interpret
202as durable acceptance, then wait for a terminal receipt. - Persist account and per-chat cursors separately; they are different cursor domains.
- Reconcile from the event log and chat journal after disconnects instead of assuming a live stream delivered everything.
- Ignore unknown event kinds and error codes unless you explicitly handle them.
- Read
customer_windowbefore choosing free-form content or a template. - Fetch template state at send time; an approved template can later be paused.
- Keep API keys and webhook signing secrets in a secret store.
Review your setup with an agent
Section titled “Review your setup with an agent”Give your coding agent the current OpenAPI document and the message-part schemas your integration uses. Ask it to verify authentication, idempotency, cursor persistence, unknown-event handling, customer-window behavior, and terminal receipt handling against those files. The served contract is more current than copied examples.
Copy this prompt into your own AI coding agent to check your integration against the guidelines above. It is the same prompt the Copy agent prompt button in the header carries.
You are auditing a codebase that integrates with Linq's WhatsApp Messages
Partner API. This is read-only: do not change code unless I ask.
First fetch the current OpenAPI contract from
`https://whatsapp.messages.api.linqapp.com/v1/openapi.yaml` and the part schemas
the integration uses (`GET /v1/parts/{type}`). If you cannot obtain them, stop
instead of auditing from memory.
Locate every API call, send path, SSE consumer, webhook handler, and cursor
store. Verify that:
- authentication uses the issued bearer key server-side and never changes its
`sk_test_` or `sk_live_` prefix;
- every logical send has a stable `Idempotency-Key`, transport retries reuse
the same key and body, and unrelated sends never share a key;
- HTTP 202 is treated as durable acceptance rather than delivery;
- free-form content is sent only in the open customer window, with an approved
template used outside it;
- unknown event kinds, error types, and error codes are handled generically
rather than crashing a consumer;
- SSE IDs, opaque account-event cursors, and numeric per-chat sequence cursors
are persisted in separate domains;
- reconnect recovery uses `GET /v1/event_log` and
`GET /v1/chats/{chat}/events`, and never assumes the live stream contained
every event;
- one inbound message cannot trigger duplicate replies from its received,
window-opened, delivered, or read events;
- webhook signatures are verified over the exact raw body, event IDs are
deduplicated, and signing-secret rotation accepts both active secrets before
the old one is retired;
- 429 responses honor `Retry-After`, terminal failures are not retried, and an
unresolved outcome is never blindly resent;
- logs include `request_id` and stable resource IDs without credentials or
message content.
Report a table with Check, Status (pass/gap/n-a/unknown), Where (file and line),
and Fix. Follow it with a short action list ordered by data-loss, duplicate-send,
and security risk. Ground every finding in code you actually read.