REST API
Tracking & events
The ingestion endpoints receive hits from the tracker (or any server-to-server sender). They do not use OAuth — they are authenticated by the site's tracking key (tracking_key, a UUID) sent in the key body field.
A hit is validated, then queued for processing, so a successful call returns 202 Accepted with an empty body. An unknown key returns 404 Not Found. All ingestion endpoints accept a text/plain body (for navigator.sendBeacon) as well as JSON.
Base URL: https://clickbase.so/api.
Collect a pageview
POST /api/collectRecord a pageview. Rate limit: 600/min per IP.
| Parameter | Type | Required | Description |
|---|---|---|---|
key |
string (uuid) | Yes | The site's tracking key. |
hostname |
string | Yes | Max 255 chars. |
url.path |
string | Yes | Max 2048 chars. |
url.title |
string | No | Max 512 chars. |
properties |
object | No | Custom property map. Max 50 keys (key ≤ 64 chars, scalar values ≤ 500 chars). |
referrer |
string | No | Max 2048 chars. |
screen.width |
int | No | 0–65535. |
screen.height |
int | No | 0–65535. |
language |
string | No | Max 35 chars. |
os |
string | No | Max 50 chars. |
os_version |
string | No | Max 50 chars. |
browser.name |
string | No | Max 50 chars. |
browser.version |
string | No | Max 50 chars. |
device |
string | No | One of desktop, mobile, tablet. |
visitor_id |
string (uuid) | No | Client-supplied visitor id (cookieless mode). |
Status: 202 Accepted (404 on unknown key).
curl -X POST https://clickbase.so/api/collect \
-H "Content-Type: application/json" \
-d '{
"key": "{tracking_key}",
"hostname": "example.com",
"url": { "path": "/pricing", "title": "Pricing" },
"referrer": "https://google.com"
}'Record a custom event
POST /api/eventRecord a named custom event, optionally carrying revenue. Rate limit: 600/min per IP.
| Parameter | Type | Required | Description |
|---|---|---|---|
key |
string (uuid) | Yes | The site's tracking key. |
hostname |
string | Yes | Max 255 chars. |
name |
string | Yes | Event name. Max 255 chars. |
properties |
object | No | Custom property map (same limits as /collect). |
url.path |
string | No | Max 2048 chars. |
url.title |
string | No | Max 512 chars. |
referrer |
string | No | Max 2048 chars. |
screen.width / screen.height |
int | No | 0–65535. |
language / os / os_version |
string | No | Device context (same limits as /collect). |
browser.name / browser.version |
string | No | Max 50 chars. |
device |
string | No | desktop, mobile, or tablet. |
visitor_id |
string (uuid) | No | Client-supplied visitor id. |
revenue.amount |
number | No | > 0. The tracker sends this under the wire field $; direct callers may send revenue. A malformed revenue shape is silently dropped, never a 422. |
revenue.currency |
string | No | 3-letter ISO 4217 code. Required with revenue. |
Status: 202 Accepted (404 on unknown key).
Send an engagement ping
POST /api/engageRecord a scroll-depth / engaged-time delta for an existing pageview. Rate limit: 600/min per IP (its own bucket).
| Parameter | Type | Required | Description |
|---|---|---|---|
key |
string (uuid) | Yes | The site's tracking key. |
hostname |
string | Yes | Max 255 chars. |
url.path |
string | Yes | Max 2048 chars. |
url.title |
string | No | Max 512 chars. |
sd |
int | Yes | Scroll depth 0–100. A value above 100 is clamped to 100. |
time |
int | Yes | Engaged time (ms), 0 up to 4294967295. |
visitor_id |
string (uuid) | No | Client-supplied visitor id. |
Status: 202 Accepted (404 on unknown key).
Identify a visitor
POST /api/identifyAttach a user identity to the visitor's active session. Rate limit: 120/min, keyed by tracking key + IP (this endpoint can grow the site_users table, so it has a tighter bucket).
| Parameter | Type | Required | Description |
|---|---|---|---|
key |
string (uuid) | Yes | The site's tracking key. |
hostname |
string | Yes | Max 255 chars. |
identifier |
string | Yes | Your stable user identifier. Max 255 chars. |
name |
string | No | Display name. Max 255 chars. |
avatar |
string (url) | No | Max 255 chars. |
custom |
object | No | Custom trait map. Max 50 keys (key ≤ 64 chars, scalar values ≤ 500 chars). |
visitor_id |
string (uuid) | No | Client-supplied visitor id. |
Status: 202 Accepted (404 on unknown key).
Payments API
The Payments API records and deletes revenue server-to-server. It is authenticated by the site's api_secret as a bearer token (not OAuth, not the tracking key). A missing/invalid secret returns 401. Rate limit: 60/min.
Authorization: Bearer {api_secret}Record a payment
POST /api/paymentsIdempotent on transaction_id: a replay returns the existing record with 200 instead of creating a duplicate.
| Parameter | Type | Required | Description |
|---|---|---|---|
amount |
number | Yes | > 0. |
currency |
string | Yes | 3-letter code. Must match the site's reporting currency (enforced by RecordPayment). |
transaction_id |
string | Yes | Idempotency key. Max 255 chars. |
visitor_id |
string (uuid) | No | Visitor the payment is attributed to. |
email |
string | No | Max 255 chars. |
name |
string | No | Max 255 chars. |
customer_id |
string | No | Max 255 chars. |
renewal |
bool | No | Whether this is a renewal. |
refunded |
bool | No | Whether the payment was refunded. |
is_free_trial |
bool | No | Whether this is a free-trial conversion. |
timestamp |
string (date) | No | Payment time; defaults to now. |
Response: { "message": ..., "transaction_id": ... }. Status: 201 Created on a new record, 200 OK on a replay.
curl -X POST https://clickbase.so/api/payments \
-H "Authorization: Bearer {api_secret}" \
-H "Content-Type: application/json" \
-d '{"amount": 49.0, "currency": "USD", "transaction_id": "ch_123"}'Delete a payment
DELETE /api/paymentsDelete a payment and its revenue row by transaction_id.
| Parameter | Type | Required | Description |
|---|---|---|---|
transaction_id |
string | Yes | The transaction id to delete. |
Response: 200 OK ({ "message": "Payment deleted." }), or 404 Not Found when no matching payment exists.
Stripe webhook
POST /api/stripe/webhook/{siteId}Per-site Stripe webhook receiver. {siteId} must be a site UUID. The request is authenticated by verifying the Stripe-Signature header against the site's configured webhook secret — a missing integration/secret returns 404, a bad signature returns 400. On success it dispatches to HandleStripeWebhook and returns 200 OK. Rate limit: 600/min. This endpoint is configured in the site's Stripe integration, not called by hand.