Skip to content
Docs
Browse Developers

Events API

Send events to Markalit from your servers and apps: endpoint, keys, event fields, responses and limits.

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.

KeyLooks likeForNotes
Write keypk_live_...An appPublic, as it is on every page that loads the tag. Every event must name its device and session.
Server keyksk_live_...A backendSecret, 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:

eventWhat it isNeeds
page_viewA web page where no tag runs, or an app's screenpage or screen, and a device and session
clickA click or a tapelement, a device and session, and clicks on for the property
Any other nameA custom event, such as subscription_renewedThe 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

FieldIs
ipThe visitor's IP address, server key only. Used for location, then dropped.
user_agentThe visitor's user agent. Without one, browser, operating system and device are unknown.
page.urlThe page a click or custom event happened on.
app{id, version, build, screen} for an app's events.
localeA language tag, such as nl-NL.
timezoneAn IANA zone, such as Europe/Amsterdam.
display{width, height} in points.
library{name, version} of what sent the event.
consentThe 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.

StatusMeansDo
200Read; accepted events were storedFix 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
400invalid_json, invalid_field, unknown_field, no_events, too_many_events, key_in_urlFix the request
401missing_key, or invalid_key (unknown, revoked or another region's)Check the key and endpoint
403secret_key_in_browserRotate the key, and send from a server
413body_too_large: over 1 MiB, decompressedSend fewer events at once
415unsupported_encodingSend plain JSON, or gzip
429rate_limitedRetry after Retry-After seconds
503unavailable: the events were not storedRetry 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: gzip for 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.

Was this helpful?