Base URL
/api/*. Public
endpoints (snippet delivery, event ingestion) are documented in the
beacon protocol reference.
Authentication
- Verified on every request against Clerk’s JWKS.
- Missing or malformed →
401 unauthorized. - Expired →
401 token_expired. Refresh via the Clerk client and retry. - Valid JWT for a user with no access to the requested resource →
403 forbidden.
https://app.abtestly.com only.
Server-to-server calls do not need CORS.
Rate limits
- 100 requests per minute per user across all
/api/*endpoints. - Exceeding the limit returns
429 rate_limitedwith aRetry-Afterheader in seconds. - Public endpoints (
/s,/e,/g,/m,/err) have their own limits documented on Rate limits.
Errors
All errors return JSON with a stable machine-readable code and a human-readable message.unauthorized, forbidden, not_found,
validation_failed, conflict, rate_limited, internal_error.
Endpoint reference
Every path below is underhttps://api.abtestly.com. Path parameters
are marked :name. All POST, PATCH, PUT, and DELETE calls
except where noted expect and return JSON.
Account and identity
Organization membership and permissions
Organization identity itself is managed by Clerk; ABTestly does not expose CRUD on the organization record. Everything below operates on the member roster and per-site permissions inside an org.Invitations
Sites
Experiments
Variant code history
The two read endpoints behind Code history.:variantKey is the variation’s short key, not a row id. Both answer
403 with { "error": "forbidden" } when the experiment does not exist
or you cannot read it, before any other check. Anyone who can read the
experiment can read its versions, Viewers included. There is no endpoint
that writes a version: versions are stored only as a side effect of
saving, creating, cloning and Signals drafts.
List versions
A
limit or before that is not a positive integer answers 400 with
{ "error": "validation_error" }.
Get one version
{ "revision": { ... } } with every field above plus jsCode,
cssCode and libraryKeys, in load order. A :revision that is not a
positive integer, or that this variation does not have, answers 404 with
{ "error": "not_found" }.
Unlike most errors on this page, these three carry only the error code,
with no message.
Result exports
Goals
The goals-library router is mounted under/api/sites, so every path
below sits inside a site.
Audiences
Mounted under/api/sites.
Saved locations
Mounted under/api/sites.
Mutual exclusion groups
Billing
Public endpoints
Not authenticated with Clerk. Used by the snippet on the visitor’s device.
The wire format for each of these is on the
beacon protocol page.
Not yet published
- OpenAPI spec. We are drafting one. Until it ships, treat this page as the source of truth.
- Long-lived API keys. No self-serve keys today. If you have a
server-side automation use case, tell us at
enterprise@abtestly.com. - Webhooks out. Paddle webhooks come in; we do not send outbound webhooks to your infrastructure yet.
support@abtestly.com with the endpoint
and the response you got. That is the fastest way for us to fix the
doc.