ShonyLabs
DocsPricingChangelog
Log inGet started

Getting started

IntroductionQuickstart

Tracking

Tracking snippetCustom goalsIdentify usersExclusions

Privacy

GDPR & cookieless tracking

Revenue

Transactions APIPayment connectors

Server & bots

Bots & server-side tracking

Collaboration

Team & access

Live map

Public live map

Integrations

Google Search Console

No-code platforms

WordPressGoogle Tag ManagerWebflowWixSquarespaceFramerGhostOther platforms

Reference

API reference

API reference

Base URL: https://api.shonylabs.com

Endpoints

Method & pathAuthPurpose
POST /eventsite_id in body (public)Records a pageview or goal. Sent by the tracking snippet, server-sdk, and the crawler log shipper.
POST /v1/identifyAuthorization: Bearer <api_key>Attaches a real account to a visitor from your own server.
POST /v1/transactionsAuthorization: Bearer <api_key>Records a purchase or refund.
DELETE /v1/transactionsAuthorization: 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/identify and /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.

FieldRequiredNotes
user_idYesIdentifying the same user_id from multiple devices merges them into one visitor.
visitor_idNoDefaults to server:<user_id> when omitted.
name, image, genderNoReserved fields — override the visitor's display in the dashboard.
anything elseNoUp 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.

FieldRequiredNotes
transaction_idYesIdempotency key — retried webhook deliveries record the sale once.
shonylabs_visitor_idYesLinks the sale back to the visitor who made it.
amountYes, unless refundedNon-negative number, e.g. 49.00.
currencyNoUp to 10 characters, e.g. USD.
customer_email / email, customer_name / name, customer_idNoEither key name is accepted for email/name.
renewal, is_free_trialNoBooleans.
metadataNoFlat JSON object of your own key/value pairs (plan, SKU, coupon, ...). Up to 20 keys, 64-character keys, 500-character values — see Transactions API.
timestampNoISO 8601. Defaults to request time.
refundedNoBoolean — 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 paramEffect
transaction_id / tx_idDeletes that one payment.
shonylabs_visitor_idDeletes 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.

ShonyLabs Analytics

Privacy-friendly web analytics that shows which channels actually drive revenue.

© 2026 ShonyLabs. All rights reserved.

Product

  • Log in
  • Sign up
  • Pricing
  • Changelog
  • Documentation
  • API reference

Guides

  • Quickstart
  • Tracking snippet
  • Goals
  • Transactions
  • Identify visitors
  • Cookieless tracking

Legal

  • Terms of service
  • Privacy policy
  • Data processing agreement