API reference
Base URL: https://api.shonylabs.com
Endpoints
| Method & path | Auth | Purpose |
|---|---|---|
POST /event | site_id in body (public) | Records a pageview or goal. Sent by the tracking snippet, server-sdk, and the crawler log shipper. |
POST /v1/identify | Authorization: Bearer <api_key> | Attaches a real account to a visitor from your own server. |
POST /v1/transactions | Authorization: Bearer <api_key> | Records a purchase or refund. |
DELETE /v1/transactions | Authorization: Bearer <api_key> | Removes a wrongly-recorded payment (single transaction, all of one visitor's, or a date range). |
Two kinds of credentials
- Site ID— public. It's embedded in your tracking snippet and safe to expose in client-side HTML.
- API key — secret. It authenticates
/v1/identifyand/v1/transactions, both of which can write identity or revenue data for your site, so it must stay server-side only. Manage keys — create, roll, or delete as many named keys as you need per site — under Settings → API. A key's full value is shown exactly once, right when it's created or rolled — only a hash is stored afterward, so there's no way to view it again later. If you lose it, roll the key and update wherever it's used.
POST /event
Public — authenticated only by a valid site_id, since it's called directly from the browser. See the tracking snippetdocs for what's captured automatically, and bots & server-side tracking for reporting hits that never run the browser snippet (Express, Laravel, Python, Ruby, Go examples included). Always returns 200 on success, including for events silently dropped by an exclusion rule — the tracking snippet should never treat that as a delivery failure.
POST /v1/identify
Attaches a real account to a visitor. See Identify users for browser-side usage; the table below covers the server-to-server call.
| Field | Required | Notes |
|---|---|---|
user_id | Yes | Identifying the same user_id from multiple devices merges them into one visitor. |
visitor_id | No | Defaults to server:<user_id> when omitted. |
name, image, gender | No | Reserved fields — override the visitor's display in the dashboard. |
| anything else | No | Up to 10 additional custom properties, lowercase key names, markup-stripped values. |
Response: { "success": true, "visitor_id": "..." }.
POST /v1/transactions
Records a purchase or, with refunded: true, nets one back out. Full field list and curl examples: Transactions API.
| Field | Required | Notes |
|---|---|---|
transaction_id | Yes | Idempotency key — retried webhook deliveries record the sale once. |
shonylabs_visitor_id | Yes | Links the sale back to the visitor who made it. |
amount | Yes, unless refunded | Non-negative number, e.g. 49.00. |
currency | No | Up to 10 characters, e.g. USD. |
customer_email / email, customer_name / name, customer_id | No | Either key name is accepted for email/name. |
renewal, is_free_trial | No | Booleans. |
metadata | No | Flat JSON object of your own key/value pairs (plan, SKU, coupon, ...). Up to 20 keys, 64-character keys, 500-character values — see Transactions API. |
timestamp | No | ISO 8601. Defaults to request time. |
refunded | No | Boolean — nets the original transaction_id's revenue back out instead of recording a new sale. |
Response: { "message": "Payment recorded and attributed successfully", "transaction_id": "..." }.
DELETE /v1/transactions
Fully removes a payment — unlike a refund, the transaction and its revenue attribution are deleted outright rather than netted out. Provide exactly one query-string filter:
| Query param | Effect |
|---|---|
transaction_id / tx_id | Deletes that one payment. |
shonylabs_visitor_id | Deletes every payment recorded for that visitor. |
start + end (ISO 8601) | Bulk-deletes every payment recorded in that range. |
Response: { "status": "success", "data": [...] }, one entry per deleted payment. Deleting a transaction_id that doesn't exist returns 404; the visitor and date-range filters return an empty data array when nothing matches. See Transactions API for full examples.
Errors
/v1/identify and /v1/transactions return a JSON body with an error field and an appropriate status code — 401 for a missing or invalid API key, 400 for a missing or malformed required field, and, for DELETE /v1/transactions specifically, 404 when a transaction_id filter matches nothing.