SonarSend API Contacts & audience Events

Events

POST /api/events records an event against a contact from your own systems — a purchase confirmed by billing, a support ticket opened, a CRM stage change. It is the server-side counterpart to the JavaScript tracking snippet, for the things a browser cannot see.

Events feed contact scoring, segment conditions, and sequence entry triggers, so this is how an external system makes something it knows about act on sending.

Reading events back is not part of the API. A contact’s activity, and the account-wide feed, are read in the app; for bulk contact data, use a contact export.

Required scope#

EndpointScope
POST /api/eventsevents:write

Recording an event#

POST /t/{tenant_slug}/api/events
X-API-Key: sonar_xxxxx
Content-Type: application/json
{
  "contact_email": "jamie@example.com",
  "event_name": "subscription_renewed",
  "type": "renewal",
  "properties": {
    "subscription_id": "sub_987",
    "product_name": "Pro Plan",
    "value": 99.00,
    "currency": "USD"
  },
  "occurred_at": "2026-04-14T18:42:11Z"
}

Identify the contact with contact_id or contact_email — one is required. An unknown address is 404 CONTACT_NOT_FOUND by default; enable auto_create_on_event in workspace settings to have a minimal contact created from the email instead, which is what a one-call billing integration usually wants.

Returns 202 with a warnings array. Validation is deliberately lenient: a property that does not match the activity type’s recommended shape is warned about, not rejected, so a schema drift on your side never drops the event.

See event-tracking.md for the full field reference, the activity-type list, and per-type examples.

Errors#

CodeStatusMeaning
INVALID_INPUT400event_name is missing, or neither contact_id nor contact_email was given.
CONTACT_NOT_FOUND404The contact did not match, and auto_create_on_event is off.
INSUFFICIENT_SCOPE403The key is missing events:write.

See errors.md for the full envelope.