Browse Developers
Events API
The Events API takes events from your own backends and apps, beside the website tag. One endpoint takes one event or a batch, says which it stored, and lets you retry safely.
If you are building a Flutter app, the Flutter SDK sends through this API for you.
The smallest call
curl https://konta.la/v1/events \
-H "Authorization: Bearer $KONTALA_SERVER_KEY" \
-d '{"event":"subscription_renewed"}'
{"request_id": "0192f2c4-...", "accepted": 1, "rejected": [], "warnings": []}
Only event is required.
Use the endpoint shown on your property's Events API card in Markalit.
Keep a server key where your backend keeps its other secrets. Never put it in code, or in a command line your shell history keeps.
Keys
Send a key in the Authorization header as Bearer <key>.
A request with a key in the URL is refused, since URLs are kept in request logs.
| Key | Looks like | For | Notes |
|---|---|---|---|
| Write key | pk_live_... | An app | Public, as it is on every page that loads the tag. Every event must name its device and session. |
| Server key | ksk_live_... | A backend | Secret, shown once when it is made. Only it may set the visitor's IP, and a custom event sent with it may name no visitor. |
Admins make, label and revoke server keys on the property's Events API card. A revoked key is refused within a minute. A server key sent from a browser is refused, and Markalit tells you so that you can rotate it.
Events
event is the name of what happened:
event | What it is | Needs |
|---|---|---|
page_view | A web page where no tag runs, or an app's screen | page or screen, and a device and session |
click | A click or a tap | element, a device and session, and clicks on for the property |
| Any other name | A custom event, such as subscription_renewed | The Events API in the property's capture rules |
Some names are Markalit's own and are refused as custom events, including purchase, cart_add, checkout_started and other Shopify and data layer names.
Names are compared ignoring case and punctuation, so Page View is refused and told to use page_view.
Other optional fields include id, timestamp, device, session, user, org, consent, properties, page_type, page, screen and element.
Send a batch
{
"context": {"user_agent": "..."},
"events": [
{"event": "subscription_renewed", "user": "customer-42"},
{"event": "invoice_paid", "user": "customer-42", "properties": {"amount": 49}}
]
}
A batch's context is the default for every event, and an event's own context overrides it field by field.
Context
| Field | Is |
|---|---|
ip | The visitor's IP address, server key only. Used for location, then dropped. |
user_agent | The visitor's user agent. Without one, browser, operating system and device are unknown. |
page.url | The page a click or custom event happened on. |
app | {id, version, build, screen} for an app's events. |
locale | A language tag, such as nl-NL. |
timezone | An IANA zone, such as Europe/Amsterdam. |
display | {width, height} in points. |
library | {name, version} of what sent the event. |
consent | The default consent for every event. |
Join a browser visit
To attach a server event to the visit a browser is in, send the pt_did cookie's value as device, and the part of pt_sid before the dot as session.
Responses
A 200 means the request was read.
Each event is stored or refused on its own.
rejected and warnings name each event by its index and id, with a code and a sentence.
| Status | Means | Do |
|---|---|---|
| 200 | Read; accepted events were stored | Fix the events in rejected, if any. Events for a capture the property has off are refused by name, such as clicks_off or source_not_captured |
| 400 | invalid_json, invalid_field, unknown_field, no_events, too_many_events, key_in_url | Fix the request |
| 401 | missing_key, or invalid_key (unknown, revoked or another region's) | Check the key and endpoint |
| 403 | secret_key_in_browser | Rotate the key, and send from a server |
| 413 | body_too_large: over 1 MiB, decompressed | Send fewer events at once |
| 415 | unsupported_encoding | Send plain JSON, or gzip |
| 429 | rate_limited | Retry after Retry-After seconds |
| 503 | unavailable: the events were not stored | Retry after Retry-After seconds |
Retry a 429 or 503 with backoff, sending the same events with the same ids.
An event with its own id is stored once however often it arrives; one without may be stored twice.
Limits
- 200 events and 1 MiB per request, decompressed. Send
Content-Encoding: gzipfor large batches. - 1,000 events a second per key, with bursts of 10,000.
- Timestamps from 30 days ago to 24 hours ahead.
- 32 KB of properties per event.