Work through this list before your integration carries real customers. Each item links to the guide that explains it. Run the whole integration in a staging workspace first: it uses the same rules and limits as live.
Identity
- Every contact carries your own id as
externalId, and your code identifies and tracks by it. See IDs and identity. - You handle 409
CONFLICTand 409ALREADY_EXISTSfrom identify, rather than retrying them. - An address change is sent with the contact’s
externalId, so it updates the contact instead of creating a second one. - You know who merges duplicates (
mergeContacts), and when.
Consent
- Your code grants consent only when the contact agreed, and sends
consent.statement(basisandevidence) with every grant. A grant without one is refused. - Your code leaves consent flags out when it does not mean to change them: an
omitted flag keeps its value, but
falsewithdraws consent. - Your app sets
consent.pushwhen the contact opts in: every push needs it, transactional included. A device’s permission alone does not. - Unsubscribes and consent changes made in Kirora reach your systems, through the
contact.unsubscribedandcontact.consent_changedwebhooks.
Channels
- Your sending domain is verified, and has a DMARC record (
p=noneat least) if you send marketing email. - The workspace’s postal address is set if you send marketing email.
- For push, a project in the
productionenvironment has a ready app for each platform, and your server registers devices on every app start. See Push notifications. - Every template your code sends by
email.templateis published. Sends use the published version, not the draft.
Keys and retries
- Each service has its own
integrationkey with only the scopes it needs. No key is in a browser, a mobile app or source control. See Authentication. - Keys used from fixed servers carry
allowedIps. - You know each key’s expiry date (new keys expire after 90 days unless you chose otherwise) and who rotates it. Rotation can keep the old key working for up to 7 days.
- Every
POSTyou might retry sends anIdempotency-Key, derived from the action (receipt-<order id>) and generated once, before the first attempt. EveryPOSTtakes one; a batch takes one per item instead. See Idempotency. - Retries are limited to transport failures, 429 and 5xx, honour
Retry-After, and stop after a few attempts. See Errors. - Batch calls read every entry of
results, not only the status. See Batches. - Your logs keep the
X-Request-Idof every call that fails.
Webhooks
- Your endpoint verifies the signature over the raw body, in constant time, and refuses timestamps more than five minutes away. See Webhooks.
- It responds 2xx within 5 seconds and does the work afterwards.
- It deduplicates on
eventId, and accepts event types it does not know. - The signing secret is stored as a secret, and someone knows how to rotate it.
Hand-over to the marketing team
The people who build campaigns and journeys in the dashboard need to know what your integration sends them. Give them a data dictionary, kept where both teams can edit it:
| Name | Kind | Type | Example | Sent by | Owner |
|---|---|---|---|---|---|
Order Completed |
Event | — | — | Checkout service | Payments team |
order_id |
Property of Order Completed |
string | "10042" |
Checkout service | Payments team |
total |
Property of Order Completed |
number, major units | 125.5 |
Checkout service | Payments team |
plan |
Contact attribute | string | "premium" |
Billing service | Billing team |
With it, tell them:
- How contacts are identified, and what happens when someone changes their address.
- Which events and attributes are sent, and from when (
GET /v1/events/cataloglists what the workspace has received). - What your code sends itself (transactional messages) and what they control in the dashboard (campaigns, journeys, templates).
- Which test addresses and test contacts to use. Reserved addresses such as
[email protected]are never delivered. See Test addresses.
Owners
Write down a person, or a team, for each of these:
- The API keys, and their rotation.
- The webhook endpoint, and its alerts.
- The sending domain’s DNS records.
- The workspace’s admins, who create keys and invite members.
- Who contacts Kirora support, with request ids, when something breaks. See Troubleshoot your integration.