MenuAuthentication and API keys

API reference

Authentication and API keys

The public API takes a secret key in the Authorization header. Each key belongs to one site and carries the events scope, the payments scope or both.

ProductLense's public API has two endpoints, both on https://api.productlense.app:

EndpointScopePurpose
POST /api/v1/eventseventsSend events from your server
POST /api/v1/paymentspaymentsSend payments from any billing system

The tracking script does not need a key: it posts to a public endpoint identified by the site id. Keys are only for calls from your own servers.

Create a key

  1. In the ProductLense dashboard, open the site's Settings → API keys.
  2. Give the key a name (1 to 100 characters) and choose its scopes: events, payments or both.
  3. Copy the key. It is shown once.

API keys are part of the Scale plan, and only the account's owner and admins can create or delete them.

Send the key

Pass the key as a Bearer token:

HTTP
POST /api/v1/payments HTTP/1.1
Host: api.productlense.app
Authorization: Bearer mk_live_3f9a...
Content-Type: application/json

Keys start with mk_live_ followed by 48 hexadecimal characters.

curl -X POST https://api.productlense.app/api/v1/events \
  -H "Authorization: Bearer $PL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"s":"SITE_ID","e":"Trial started","u":"https://example.com/app","uid":"user_123"}'
const res = await fetch('https://api.productlense.app/api/v1/events', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.PL_API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ s: 'SITE_ID', e: 'Trial started', u: 'https://example.com/app', uid: 'user_123' }),
});
if (res.status !== 204) throw new Error(`ProductLense answered ${res.status}`);
import os
import requests

res = requests.post(
    "https://api.productlense.app/api/v1/events",
    json={"s": "SITE_ID", "e": "Trial started", "u": "https://example.com/app", "uid": "user_123"},
    headers={"Authorization": f"Bearer {os.environ['PL_API_KEY']}"},
    timeout=10,
)
res.raise_for_status()
body := strings.NewReader(`{"s":"SITE_ID","e":"Trial started","u":"https://example.com/app","uid":"user_123"}`)
req, _ := http.NewRequest(http.MethodPost, "https://api.productlense.app/api/v1/events", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("PL_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
	log.Fatal(err)
}
defer res.Body.Close()
if res.StatusCode != http.StatusNoContent {
	log.Fatalf("ProductLense answered %d", res.StatusCode)
}

Authentication errors

StatusCodeMessageCause
401unauthorizedmissing or malformed API keyNo Authorization: Bearer header, or the key does not start with mk_live_
401unauthorizedunknown or revoked API keyThe key was deleted or never existed
403forbiddenAPI key lacks the events scopeThe key does not have the scope the endpoint needs (the message names the scope)
403forbiddenapi key does not belong to this siteAn events request names a site id other than the key's site

Rotate a key

Create the new key, deploy it, then delete the old key in Settings → API keys. Deleting a key takes effect on the next request.

    ↑ ↓ to move, Enter to open