OneTrial docs
One API call answers "should this signup get a free trial?" with allow, challenge, or deny. Integration takes a snippet, one server call, and a webhook.
How it works
- The browser snippet (https://onetrial.dev/v1.js, 15 KB gzipped, async) computes a device hint and passive signals and exchanges them for a signed visitorToken (JWT, 5-minute TTL). It never shows UI.
- On form submit, your frontend reads
await OneTrial.getToken()and sends it with the signup to your backend. - Your backend calls
POST /api/v1/decisionswith the token, email, and client IP (pluscardFingerprintanduserIdwhen you have them). - You get
{ decision: "allow" | "challenge" | "deny", score, reasons[], challengeOptions[], challengeId?, challengeUrl? }.- allow: create the trial.
- challenge: send the visitor to
challengeUrl(hosted) or run the headless flow; unlock the trial on thechallenge.completedwebhook. - deny: show a paid plan or a support contact. Never expose score or reasons to the visitor.
- New workspaces start in shadow mode: every signup is scored and recorded but the API returns allow (
shadow: true, wouldBe: "..."). Flip to live from the dashboard orPATCH /api/v1/settings {"shadowMode": false}.
Secrets:
ot_test_... / ot_live_... keys are server-side only. ot_pk_... is public and goes in the snippet.Install paths
- With an AI agent: run
npx onetrial initin your project, or paste the prompt from Agent prompts. - By hand: pick a quickstart.
- Verify:
GET /api/v1/integration/statusreturns a checklist; nothing is done until it says so.