Integrations / Django

Trial abuse prevention for Django

Two additions to a Django app: a script tag on the page with your signup form, and one call from the view that handles the signup POST. The answer arrives before you create the account, so there is nothing to undo when it says no.

The tag, in your signup template

It loads asynchronously, renders nothing, and exchanges a device hint for a signed token that lives five minutes. No decision is ever made in the browser, so nothing here can be edited by a visitor to change the outcome.

<script src="https://onetrial.dev/v1.js" data-key="YOUR_PUBLIC_KEY" async></script>

Read the token when the form submits and send it along with the rest of the fields.

// Signup form (browser): include the token in your POST
const token = await OneTrial.getToken(); // window.OneTrial is set by the snippet
OneTrial.markSubmit(); // records time-to-submit
formData.append('visitorToken', token);

The call, in the view that handles the signup POST

Your key stays on the server. Send the token, the canonical email and the client IP, plus a card fingerprint and your own user id when you have them. The median answer takes under 300ms.

import os, requests
r = requests.post("https://onetrial.dev/api/v1/decisions",
headers={"Authorization": f"Bearer {os.environ['ONETRIAL_API_KEY']}"},
json={"visitorToken": visitor_token, "email": email, "ip": ip, "userId": user_id}, timeout=5)
d = r.json()
if d["decision"] == "deny": return paid_plan_or_support()
if d["decision"] == "challenge": return redirect(d["challengeUrl"]) # trial unlocks on the webhook
create_trial(user_id)

The three answers

allow creates the trial as normal. challenge asks for one proof, either on a page we host at challengeUrl or inside your own UI, and the trial unlocks on the challenge.completed webhook. deny shows a paid plan or a way to reach you.

Never show the score or the reasons to the visitor. They are for your dashboard, your logs and your own judgement, because anyone told which signal caught them knows what to change next time.

Or let the CLI write it

It detects Django, writes the environment variables, injects the tag and then calls the API once to prove the install works before it reports success.

npx onetrial init

Before you enforce anything

Every new workspace starts in shadow mode: signups are scored and recorded, and your Django app is always told allow. Read a week of your own decisions first, then turn enforcement on when the answers match the judgement you would have made yourself.

Next: how a signup becomes a verdict, what trial abuse costs, or the full Django quickstart with webhooks and challenges.