API
Improve API
Talk to Improve over HTTP: the datafile, analytics and agent APIs, the OpenAPI spec and authentication.
If you're running Improve on a Javascript server environment it's recommended to use the Javascript SDK which interfaces with the API for you. If that doesn't work for you because of alternative server languages you can interface directly with the API.
The Improve API is split up in two parts;
OpenAPI spec
The public API is described as OpenAPI 3.1 at /openapi.json: every operation has an operationId, typed parameters, request bodies and response schemas. Load it into an HTTP client, a code generator or an LLM tool-calling setup instead of hand-writing requests.
curl https://improve.obelism.studio/openapi.jsonSecurity
To make sure your usage is actually from you we protect endpoints in two different ways for server and client.
Server side
Server requests send an API token (imp_…) in a token header. It belongs to one space and environment, and is for servers only. Create one under API tokens on the Settings page, for the environment you are editing. Only a hash of it is stored, so it is shown once, when created: copy it into your server's environment right away. Every token expires: in 30 days, 90 days, 1 year (the default) or never, picked when you create it. After that it is refused like a revoked one, and the list marks a token that expires within 14 days. The organization's admins and the person who created it get an email 14 and 3 days before. An environment can have several tokens, so to replace one, create the new token, deploy it, then revoke the old one. If a token leaks, revoke it.
- Analytics (
/api/log) needs the token: a server request without a valid one gets403. - The datafile (
/config) is also served without a token, rate limited per IP. A valid token lifts that limit, so send it from servers that render many pages. Every request is still held to 100 per 10 seconds per IP at the edge.
curl --header "token: imp_…" https://improve.obelism.studio/config/ORG/ENV/STATEWithout a stored token
A deployment on Vercel, or a GitHub Actions workflow, can send the OIDC token its host gives it instead of an API token: nothing to store or rotate. Connect it first, under Connected deployments on the space's page on www.obelism.studio: its Vercel team and project ids or its GitHub repository id, and a rule per environment of the deployment mapping it to one environment of the space, with Improve on (which also lets it send numbers events). Then pass the server SDK a token source, which sends the host's token in the same token header:
import { ImproveServerSDK } from '@obelism/improve-sdk/server'
import { vercelOidc } from '@obelism/improve-sdk/oidc' // needs @vercel/oidc installed
const improve = new ImproveServerSDK({
organizationId: 'org_…',
environment: 'production',
token: vercelOidc(), // or githubOidc() in a workflow with `permissions: id-token: write`
})Shopify Oxygen issues no OIDC token, so a storefront there uses an API token (imp_…) instead; see React Router.
Without the SDK, request the host's token for https://improve.obelism.studio (the datafile) or https://numbers.obelism.studio (analytics) and send it yourself.
A token from another team, project or repository, for another audience, expired, or whose rule has Improve off, counts as no token. A token whose rule maps it to another environment than the one in the URL (or the event) is refused with 403: a preview deployment reads the environment its rule names, never production by asking for it.
When a connected deployment reaches the environment you are editing, the Settings page has Copy for connected deployments next to Copy as .env: the same variables without a token line.
Local development
vercelOidc() works on your own machine too. Link the repository to the Vercel project with vercel link and sign in with vercel login: the SDK takes the token vercel env pull wrote to your .env, or asks Vercel for a new one with your sign-in when there is none or it expired. That token's environment is development, so the connection needs a rule for development with Improve on (its template maps it to develop), and the SDK's environment names the same environment. Only members of the Vercel team get a token: anyone else, and CI outside Vercel and GitHub Actions, uses an API token.
Client side
Client side validation is done by CORS; from the console you can specify which origin is allowed to make requests per environment. Requests from an origin that isn't allow-listed are rejected with 403, so make sure every environment lists the origins your site actually serves from before going live; otherwise the SDK falls back to default values and analytics are dropped.
Rate limits & quotas
Plans and pricing are paused: every organization currently has unlimited datafile and analytics usage, so the quotas below do not apply. They return with the plans.
The datafile endpoint rate-limits the browser path per IP (429 when exceeded); server requests with a valid token are exempt. On top of that, every datafile request is limited at Cloudflare's edge to 100 per 10 seconds per IP, with or without a token. Analytics requests are bounded too: oversized bodies return 413 and invalid payloads 400. The agent API's account endpoints are limited per email address. Rate limited endpoints state their policy in a RateLimit-Policy header, and a 429 adds RateLimit and Retry-After.
Your plan's monthly quota works differently, and deliberately never returns an error. Quotas are measured per organization — all three environments draw on one allowance — and cover two meters: datafile requests and analytics events. Going over either one never affects your visitors: the datafile keeps being served and every analytics event is still accepted and stored. Instead the platform pauses its own work on your behalf:
- Past your analytics quota, test results stop being recalculated, so the dashboard stops moving. Nothing is lost — the data is still being recorded, and results catch up with no gap once the quota clears.
- Past your datafile quota, your datafile is frozen at its last version. Visitors keep getting your tests and flags exactly as they were configured at that moment, but changes you make in the dashboard won't reach them.
Every datafile request counts, including those answered from Cloudflare's cache, and usage is updated hourly. Both lift automatically when the new month starts, or immediately on moving to a bigger plan, which an admin does on the organization's page on obelism.studio. Admins are emailed at 80% and at 100% of each quota. See the Datafile, Analytics and Versioning pages for specifics.
Versioning
The public API is version 1, sent on every response as Api-Version: 1. Send the same header on a request to pin the version: one that isn't served gets a 400. Breaking changes ship under a new path prefix, never in place, and a retiring endpoint sends Deprecation and Sunset headers at least 6 months ahead. See Versioning.