Decide who gets your free trial before you pay for it.
Lanitor sits between signup and the credits. Before your backend grants anything that costs you money, one call tells it whether to allow, limit, challenge or deny — and why.
// lanitor.evaluate("signup_credits", 100)
{
action: "deny",
amount: null,
challenge: null,
reasonCodes: [
"DEVICE_SIX_ACCOUNTS",
"RELATED_CONFIRMED_ABUSE"
]
}
The four decisions
-
allow
The full 100 credits. Most users land here.
-
limit
10 credits now. The rest once they show they're real.
-
challenge
Verify a phone or card before anything is granted.
-
deny
The account can exist. The promotion can't.
Every decision comes with its reasons.
No single signal is proof of anything. Lanitor combines device continuity, network, email, signup velocity, payment history and what happened to related accounts, then tells you what tipped it.
| User | Entitlement | Decision | Reason codes |
|---|---|---|---|
usr_8f2k |
signup_credits |
allow | FIRST_DEVICE RESIDENTIAL_NETWORK |
usr_c41m |
signup_credits |
limit 10 of 100 | DEVICE_PREVIOUS_TRIAL |
usr_2abq |
referral_reward |
deny | PAYMENT_PREVIOUSLY_REWARDED NETWORK_HIGH_VELOCITY |
usr_77ez |
api_trial |
challenge phone | EMAIL_DISPOSABLE NETWORK_DATACENTER |
usr_d09h |
daily_credits |
allow | KNOWN_GOOD_CUSTOMER |
usr_e13r |
signup_credits |
deny | DEVICE_SIX_ACCOUNTS RELATED_CONFIRMED_ABUSE |
It protects the thing after signup.
Auth decides who gets an account. Lanitor decides who gets the credits. A twentieth account is easy to make, and worth nothing.
Friction only where the risk is.
Most users notice nothing. The thresholds are yours, per entitlement, because four dollars a generation and four cents a generation need different rules.
Start in shadow mode.
Lanitor decides without enforcing. See who would have been limited or denied, how many of them later paid, and what it would have saved. Then switch it on.
Two packages, four calls.
identify, track, evaluate, feedback. If Lanitor is unreachable, your configured fallback applies. A signup never breaks because of us.
const decision = await lanitor.evaluate({
userId: user.id,
sessionToken,
entitlement: "signup_credits",
amount: 100
})
if (decision.action === "limit") {
await grantCredits(user.id, decision.amount)
}