Skip to content

Send events from your backend

Get a public access key, send it as a bearer token to the Events API, and replace it without a gap when it has been exposed.

A public access key lets your own backend send events to Tracking. It is a secret that belongs to one product and belongs on your server — never in a browser, a mobile app, a public repository or anywhere a visitor could read it.

The tracking script does not use a key and never needs one. Keys exist for the things the browser cannot see: a payment confirmed by your payment provider, a subscription renewal, a refund, an order that completes on a checkout you do not host. Those arrive from your backend, authenticated with a key.

Keys are not a tracking setting. The platform issues them and checks them at the edge, for every toolkit at once, so there is nothing about them to manage inside Tracking.

Get a key

Keys live on the product the events belong to, under ProductSettingsPublic Access. A product Owner or Admin creates them. The screen itself belongs to the platform, not to Tracking.

Creating one asks for a name and a scope. The name is for you — it is what tells two keys apart in the list and has no effect on what the key can do.

A key you create there starts with lpk_ followed by 32 hexadecimal characters, and is shown once — in the dialog that opens the moment the key is created. Copy it then and store it wherever your backend keeps its secrets. Only a hash of it is kept, so nobody, including Lessly, can show it to you again. Lose it and your only option is to replace the key.

Each key carries a scope, which you choose when you create it and can change later:

  • every public route of the product;
  • every public route of one toolkit — tracking, for a key that sends events;
  • or, through the management API rather than the screen, a single route — which for Tracking means POST /events.

A key is bound to the product it was created in. There is no key that spans products, so a key from your staging product cannot write into your production one by mistake.

Send it

Send your events to the Events API endpoint with the key as a bearer token — whichever key you hold, whatever it starts with:

Authorization: Bearer YOUR_KEY_HERE

The endpoint is https://<tracking host>/<product id>/tracking/events. The host is written as a placeholder because it depends on your product: it is the shared Lessly edge until you claim a host on a domain of your own on the Tracking domain page. Tracking’s Public access page shows the endpoint filled in for your product and lets you copy it.

The key is checked before the request reaches Tracking, and is removed from the request on the way through, so Tracking never sees it.

What the request body looks like, which names carry revenue and how amounts are expressed are on Send revenue from your backend. The route, its status codes and its schema are on the Tracking API reference.

The other carriers

Two more headers carry the same key. X-Public-Key is the platform’s own alternative to the bearer token, and X-Api-Key is a legacy alias that still works and will keep working:

X-Public-Key: YOUR_KEY_HERE
X-Api-Key: YOUR_KEY_HERE

It is there for integrations written against Tracking’s own key check, which sent the key that way. Nothing that already sends X-Api-Key has to change — not the header, and not the value in it. New integrations should use Authorization: Bearer, which is the documented carrier everywhere on the platform.

The headers are read in that order — Authorization: Bearer, then X-Public-Key, then X-Api-Keyby presence, not by validity. A wrong key in a higher-priority header is refused rather than a reason to look at the next one. An Authorization header carrying any other scheme is ignored, so a browser’s Basic prompt is never mistaken for a key.

The keys you already had

Nothing you are running has to change. Keys that Tracking issued itself — the ones starting with sk_live_ — carry over to Public Access as they are. The secret is the same string it always was: an sk_live_ key stays an sk_live_ key and is never reshaped into an lpk_ one, so a backend sending the key it has today keeps being accepted, on either carrier. There is no migration for you to do and nothing for your customers to notice.

Those keys appear in the list marked as imported, keeping the name and creation date they had, with no member named as their creator, and scoped to the tracking toolkit — every keyed tracking route, which is what they could already reach. From then on they are managed like any other key: an Owner or Admin can narrow their scope or revoke them.

Two things that carry over are worth knowing:

  • The plaintext is not shown again. A key is carried over for the systems already holding it, not handed back to you, so Public Access shows the same first few characters and no more.
  • A key you had already revoked stays revoked. Only keys that are still active carry over, and revoking one afterwards is permanent.

Replace a key

There is no rotate button, and that is on purpose: replacing a key is three steps you control the timing of.

  1. Create the new key and copy its secret.
  2. Deploy it to whatever sends events, and confirm the events are still arriving.
  3. Revoke the old key.

Do it in that order and there is no window in which your backend is refused. Doing it the other way round — revoking first — stops your events until the new secret is deployed.

Replace a key when a secret may have been exposed — a leaked log, a laptop that left the building, someone who has moved on — and on whatever schedule your own policy sets.

When a change takes effect

Creating or revoking a key is not instant at the edge. The check runs against a snapshot that refreshes about every 30 seconds, so a new key may be refused for a moment after you create it, and a revoked key may be accepted for the same moment after you revoke it. Plan for half a minute either way.

When a request is refused

CodeWhat it means
401 public_key_requiredNo key reached the edge on any of the accepted headers.
401 public_key_invalidThe key is not one of this product’s keys. A revoked key reads the same way.
403 public_key_scopeThe key is real, but its scope does not cover the Events API.
503 public_config_unavailableThe edge has not loaded its key snapshot yet. It fails closed rather than letting a request through unchecked — retry.

Fix a rejected request walks through what to check for each.

Keep keys safe

  • One key per system that sends events, so you can replace exactly the one that is compromised without stopping everything else.
  • Scope a key to what it actually calls. A key that only sends events has no business covering every public route of the product.
  • Keep secrets in your deployment’s secret store, not in source control or a configuration file that travels with your code.
  • Never put a key in anything that runs in a browser. The tracking script covers what happens in the browser and needs no key.
  • Revoke keys you no longer use: an active key nobody is watching is the one that gets found.

Next steps

Was this page helpful?
Esc

Start typing to search the docs.

navigateselect