stile
HTTP API

Compliance

Look up regulatory rules by product type and jurisdiction — required age tiers, prohibited products, allowed verification methods, and most-restrictive resolution for mixed carts.

The Compliance API tells you what the rules are before you ask anyone to verify. Give it one or more product types and a jurisdiction, and it returns the required age tier, whether the product is prohibited, and which verification methods that jurisdiction permits. Use it to:

  • Pre-check carts — catch prohibited products before checkout, not after the user has verified
  • Show age requirements in your UI — display "21+ required in California" before launching verification
  • Pick between workflows — when you run multiple published workflows, choose the one whose use case matches what the rules require
  • Resolve mixed carts — multiple product types collapse into one most_restrictive summary: the highest age tier, the intersected allowed methods

Sessions handle this automatically

When you create a verification session, compliance is resolved internally from the workflow's use case and the user's jurisdiction — you don't need to call this API first. Use it when you want to inspect the rules yourself: pre-checking carts for prohibited products, showing age requirements in your UI, or picking between workflows.

Check compliance

GET/v1/compliance/check

Returns compliance details for one or more product types in a jurisdiction, plus a most_restrictive summary that merges the rules across all products.

ParameterTypeDescription
use_casesrequiredstringComma-separated product types to check (max 10). E.g. "alcohol_delivery,tobacco_nicotine".
jurisdictionstringJurisdiction to check against (e.g. "US-CA", "US-UT"). If omitted, auto-detected from request IP / geo headers.

Available product types

Product typeDescription
alcohol_deliveryAlcohol delivery (online orders)
alcohol_in_personAlcohol retail (point-of-sale)
cannabis_dispensaryCannabis dispensary sales
cannabis_deliveryCannabis delivery
gambling_onlineOnline gambling / iGaming
gambling_in_personIn-person gambling / casinos
tobacco_nicotineTobacco and nicotine products
adult_contentAdult content / pornography
social_mediaSocial media age gates
firearmsFirearms sales

Example: single product

Check one product type against an explicit jurisdiction:

curl "https://api.stile.id/v1/compliance/check?use_cases=alcohol_delivery&jurisdiction=US-CA" \
  -H "Authorization: Bearer stile_sk_..."
import requests

res = requests.get(
    "https://api.stile.id/v1/compliance/check",
    headers={"Authorization": "Bearer stile_sk_..."},
    params={"use_cases": "alcohol_delivery", "jurisdiction": "US-CA"},
)
result = res.json()
print(result["most_restrictive"]["required_age_tier"])
# "min_age_21"
req, _ := http.NewRequest("GET", "https://api.stile.id/v1/compliance/check?use_cases=alcohol_delivery&jurisdiction=US-CA", nil)
req.Header.Set("Authorization", "Bearer stile_sk_...")
res, _ := http.DefaultClient.Do(req)
const result = await stile.compliance.check({
  use_cases: ["alcohol_delivery"],
  jurisdiction: "US-CA",
});

console.log(result.most_restrictive.required_age_tier);
// "min_age_21"

Example: mixed cart

When a cart contains multiple product types, the API returns per-product details and a merged most_restrictive summary with the highest age tier and intersected allowed methods. If any single product is prohibited, any_prohibited flips to true and the offending product types are listed in prohibited_use_cases.

curl "https://api.stile.id/v1/compliance/check?use_cases=alcohol_delivery,tobacco_nicotine&jurisdiction=US-UT" \
  -H "Authorization: Bearer stile_sk_..."
import requests

res = requests.get(
    "https://api.stile.id/v1/compliance/check",
    headers={"Authorization": "Bearer stile_sk_..."},
    params={
        "use_cases": "alcohol_delivery,tobacco_nicotine",
        "jurisdiction": "US-UT",
    },
)
result = res.json()

if result["most_restrictive"]["any_prohibited"]:
    print("Cannot sell:", result["most_restrictive"]["prohibited_use_cases"])
req, _ := http.NewRequest("GET", "https://api.stile.id/v1/compliance/check?use_cases=alcohol_delivery,tobacco_nicotine&jurisdiction=US-UT", nil)
req.Header.Set("Authorization", "Bearer stile_sk_...")
res, _ := http.DefaultClient.Do(req)
const result = await stile.compliance.check({
  use_cases: ["alcohol_delivery", "tobacco_nicotine"],
  jurisdiction: "US-UT",
});

// Check if any products are prohibited in this jurisdiction
if (result.most_restrictive.any_prohibited) {
  console.log("Cannot sell:", result.most_restrictive.prohibited_use_cases);
  // Remove prohibited items from the cart
}

// Per-product details
for (const r of result.results) {
  console.log(r.use_case, r.prohibited ? "PROHIBITED" : r.required_age_tier);
}

// Create a session — the workflow carries the use case, and the
// age tier is resolved internally
const session = await stile.verificationSessions.create({
  type: "age",
  workflow_id: "wf_YOUR_WORKFLOW_ID",
});

Response

The response includes the resolved jurisdiction, a results array (one entry per product type), and a most_restrictive summary.

{
  "jurisdiction": "US-CA",
  "jurisdiction_source": "explicit",
  "results": [
    {
      "use_case": "alcohol_delivery",
      "jurisdiction": "US-CA",
      "prohibited": false,
      "prohibited_reason": null,
      "required_age_tier": "min_age_21",
      "allowed_methods": ["mdl", "facial_age", "carrier_lookup", "document_capture"],
      "mdl_acceptance_status": "supplementary",
      "governing_regulator": "State Alcohol Beverage Control Boards",
      "consent_required": false,
      "credential_validity_days": 365,
      "rule_version": "2026-04-02"
    }
  ],
  "most_restrictive": {
    "required_age_tier": "min_age_21",
    "allowed_methods": ["mdl", "facial_age", "carrier_lookup", "document_capture"],
    "consent_required": false,
    "data_retention_days": null,
    "any_prohibited": false,
    "prohibited_use_cases": []
  }
}

Top-level fields

ParameterTypeDescription
jurisdictionstringThe jurisdiction the check was resolved against.
jurisdiction_sourcestring"explicit" when you passed a jurisdiction, "auto_detected" when it was resolved from the request.
resultsobject[]One entry per product type checked. See per-result fields below.
most_restrictiveobjectMerged summary across all product types. See summary fields below.

Per-result fields

ParameterTypeDescription
use_casestringThe product type that was checked.
jurisdictionstringThe jurisdiction this rule was evaluated against.
prohibitedbooleanWhether this product is prohibited in the jurisdiction.
prohibited_reasonstring | nullWhy the product is prohibited (e.g. state law citation).
required_age_tierstring | nullThe age tier required for this product. E.g. "min_age_21", "min_age_18".
allowed_methodsstring[]Verification methods permitted in this jurisdiction for this product.
mdl_acceptance_statusstringHow mobile driver's licenses are treated under this rule: "full", "supplementary", "not_recognized", or "unknown".
governing_regulatorstring | nullThe regulatory body (e.g. State ABC, FDA).
consent_requiredbooleanWhether explicit user consent is required.
penalty_descriptionstring | nullPenalty for non-compliance (e.g. "Up to $10K/day per violation").
penalty_typestring | null"CIVIL", "CRIMINAL", or "BOTH".
credential_validity_daysnumberHow long a verification credential remains valid (in days). When a user verifies, their credential expires after this many days — forcing re-verification. Varies by jurisdiction and product type (e.g., 30 days for gambling, 365 for alcohol).
rule_versionstring | nullVersion identifier of the rule set this result was computed from.

Most-restrictive summary fields

ParameterTypeDescription
required_age_tierstring | nullThe highest age tier across all non-prohibited products.
allowed_methodsstring[]Intersection of allowed methods across all non-prohibited products.
any_prohibitedbooleanTrue if any product type is prohibited in this jurisdiction.
prohibited_use_casesstring[]List of product types that are prohibited.
consent_requiredbooleanTrue if any product requires explicit consent.
data_retention_daysnumber | nullShortest data retention limit across all products.

Age tiers are ordered: min_age_13 < min_age_16 < min_age_18 < min_age_21. The summary returns the highest tier required by any non-prohibited product in the cart — a verification at a higher tier satisfies any lower requirement, never the reverse.

Typical integration flow

The Compliance API is informational — it tells you the rules but doesn't enforce them. Your application decides what to do with the results.

Server-side flow:

  1. Call stile.compliance.check() with the product types in the user's cart and their jurisdiction
  2. If any products are prohibited, remove them from the cart or show an error before starting verification
  3. Create the session with the matching workflow_id — the age tier is resolved internally from the workflow's use case

Widget flow (automatic):

  1. Point the widget at a published workflow (workflow-id, or let your session-url endpoint choose one)
  2. Session creation resolves compliance from the workflow internally — no extra API call needed

Next steps

On this page