Skip to main content
A restriction policy says where your app may take real money and from what age. It is one JSON document with two parts: geo, the countries and regions that are open or blocked, and age, the minimum age by country and region. Your server evaluates it against the verified session before every paid action, and refuses when it says no. An app built in Bankroll’s builder receives its policy from Bankroll in its BANKROLL_RESTRICTIONS setting. A self-hosted app sets the same setting itself.

The policy

The codes above are an example of the shape, not a policy. Countries are ISO 3166-1 alpha-2 codes and regions are ISO 3166-2 suffixes, checked by shape only, so every region of every country is accepted. Letter case does not matter. A full code such as "US-CA" under "US" is accepted and reduced to its suffix. A policy with an unknown key, a bad code, or a region in both lists is refused when it is read.

How it is evaluated

  • No policy means no restriction. An unset or empty setting restricts nothing. Whether the player has verified at all is a separate gate.
  • The age rules come first. A session with no verified age is refused. A policy with no age part holds the player to 18.
  • The location rules fail closed. A country with allow or block regions needs the session’s region; without it the location is unknown and paid play is off. A policy with any country rule needs the session’s country.
  • The age rules ask for the region only when it could change the answer. A 30-year-old whose location resolved only to US passes under a policy that says 21 in one state, because 30 clears every minimum in the country. A 20-year-old does not, and is refused until the region resolves.
The result is one verdict: minimumAge comes with it: the minimum the player was held to, when the policy resolves one.

Use it in your app

@joinbankroll/sdk/restrictions reads the setting and evaluates a session. It has no dependencies.
Decide on the server, from the verified session. Never from a location or an age the browser sent. The starter wraps the two calls as paidPlayRestriction(session) in src/lib/restrictions.ts, its /api/me route returns the verdict as restriction so the UI can disable paid actions and say why, and the P2P engine’s example route refuses on it. restrictionPolicyFromEnv() throws on a malformed setting instead of allowing play. readRestrictionPolicy(document) reads a policy from anywhere else, in canonical form.