Send product events to see how clients use your product.
Report what your users do (a report exported, a feature opened) and Revvly shows it on each client’s Usage tab, in the cross-client overview and in the support ticket of the person who wrote in. Nothing here is billed: for metered, billable usage use the Event Ingestion API.
Authentication
A Bearer API key that holds PRODUCT_EVENT_WRITE (“Can send product events”). No existing key has it: grant it when you issue a key. It is not the same as USAGE_WRITE, and a key for one cannot call the other. The workspace is the key’s own; nothing in the body names a tenant.
Authorization: Bearer rvly_sk_live_<your-token> Content-Type: application/json
#Send events
POST /api/v1/product-events: 1 to 100 events per request, answered 202 with one result per event. One bad event is refused on its own and never sinks the others.
curl -X POST https://api.revvly.ai/api/v1/product-events \
-H "Authorization: Bearer rvly_sk_live_<your-token>" \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"eventId": "evt_8f2c",
"event": "report.exported",
"userId": "u_1042",
"clientId": "acme",
"timestamp": "2026-11-01T09:30:00Z",
"properties": { "format": "pdf", "rows": 240 }
}
]
}'Response{
"results": [
{ "eventId": "evt_8f2c", "status": "ACCEPTED" }
]
}Each result is ACCEPTED, DUPLICATE or REJECTED with a reason that says what to fix.
Events are kept for 13 months, then removed.
#Mint a browser token
POST /api/v1/product-events/tokens: your backend asks for a token for the person who is signed in. It takes a userId and/or a clientId (at least one) and an optional ttlSeconds (60 to 3600, default 900), and needs the same PRODUCT_EVENT_WRITE key. Hand the token to the page and mint a new one before it expires. Revoking the key stops every token it minted.
curl -X POST https://api.revvly.ai/api/v1/product-events/tokens \
-H "Authorization: Bearer rvly_sk_live_<your-token>" \
-H "Content-Type: application/json" \
-d '{ "userId": "u_1042", "clientId": "acme", "ttlSeconds": 900 }'
# { "token": "eyJ...", "expiresAt": "2026-11-01T10:15:00.000Z" }#Send events from the browser
POST /api/v1/product-events/browser with the token as a Bearer credential. Same events, validation and masking as the server route, at most 50 per request, and an optional sessionId that groups a visit.
// In the page, with the token your backend handed it.
await fetch('https://api.revvly.ai/api/v1/product-events/browser', {
method: 'POST',
keepalive: true, // lets the request finish while the page closes
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
events: [
{
event: 'page.viewed',
sessionId: 's_7f3a',
properties: { path: '/reports' },
},
],
}),
});Browser SDK
One script that does the browser half for you: it records a page.viewed on load and on every single-page navigation, a page.left with the seconds the page was actually visible (activeSeconds), and whatever you track. Events carry a session id that changes after 30 minutes without activity, so Revvly can show sessions, session length and top pages.
There is no package to install: Revvly serves the script from the address you sign in to the dashboard at, and a page loads the current version each time. The step-by-step setup (key, clients, allowed sites, token route) is in Set up product event tracking.
<script src="https://<your-revvly-address>/revvly-events.js"></script>
<script>
RevvlyEvents.init({
// Ask YOUR backend for a token: it calls POST /api/v1/product-events/tokens
// with its API key. Called again before the token expires.
getToken: () => fetch('/my-backend/revvly-token').then((r) => r.text()),
});
// Page views and time on each page are recorded for you. Add your own:
RevvlyEvents.track('report.exported', { format: 'pdf' });
</script>The two events it makes, page.viewed and page.left, appear in Settings → Product events like any other; leave them as they are to feed the session views.
#Erase one user
DELETE /api/v1/product-events/users/:userId removes every stored event of that user (a data-subject request), in your workspace only. Same key and capability; it answers the number deleted and cannot be undone.
curl -X DELETE https://api.revvly.ai/api/v1/product-events/users/u_1042 \
-H "Authorization: Bearer rvly_sk_live_<your-token>"
# { "eventsDeleted": 312 }