Skip to content

Going live

  • The production key is not the one you developed with. Development keys end up in shell history, screenshots and chat threads.
  • It carries only the scopes the integration uses. Check GET /v1/me against what your code actually calls.
  • It lives in your environment or secret manager, never in the repository.
  • If your integration calls from fixed addresses, they are on the key’s allowlist. A leaked key is then useless from anywhere else.
  • One key per system. Revoking your store’s key should not take your ERP down with it.
  • Every send that matters carries an Idempotency-Key derived from the event, not from the attempt. This is the difference between a retry and a duplicate charge.
  • You handle 429 by honouring Retry-After rather than looping.
  • You branch on error.code, never on error.message.
  • Anything outside the 24-hour window uses an approved template. Check window_open_until rather than assuming.
  • Template parameters are built from template.parameters rather than hard-coded, so a template edited in the dashboard cannot start sending messages with gaps.
  • Bulk sends go through a campaign, not a loop.
  • Signatures are verified against the raw request body, before parsing.
  • The comparison is constant-time.
  • Deliveries older than five minutes are rejected.
  • Your endpoint replies 2xx immediately and works afterwards.
  • Events are deduplicated on X-KM-Delivery-Id.
  • Unknown event types are ignored, not treated as errors.
  • You subscribe to message.failed and do something with it. A send that quietly failed is worse than one that failed loudly.
  • Delivery failures are surfaced somewhere a person will see. The webhook delivery history covers our side; your side needs its own alerting.
  • Someone knows how to rotate the key, and it is written down.
  • You have checked the number’s quality_rating. A drop towards RED precedes a cut to your messaging limit, and the usual cause is sending people things they did not ask for.

Point a staging key at a real number you own and run the whole path: send a template, confirm the delivery webhook lands, reply from the phone, confirm the incoming webhook lands. It takes ten minutes and catches the things that only appear end to end, such as a signature check that works against your own test payload but not against the raw bytes we actually send.