Before you start
You need:- The Risk Platform turned on for your account. Contact sales if it isn’t.
- Your Site key and a Secret key, from Risk Platform > API Keys in the dashboard. The Site key is safe in browser code and only works from your allowed origins. The Secret key stays on your server. See Keys.
- Node 18 or later for the JavaScript SDK, or Python 3.9 or later for the Python SDK.
- Access to the SDK packages. They are private for now: ask your Abstract contact to give your team access.
1. Browser: collect a device token
Create one client for your app, start it on the signup or login page, and attach the token to the request your form already sends.Your Site key works only on the web addresses allowed for it. Before you test, add each origin your signup and login pages run on (for example
https://app.example.com and http://localhost:3000) by asking support."login" on your login page. What each call does:
start(flow)loads the collection script in the background and returns a cleanup function. Return it from your effect, or call it when the page unmounts. Start only the flow of the current page, not both flows in a global layout.withToken(flow, init)adds the device token to your request in thex-abstract-device-tokenheader. If no token is ready, it returns your request unchanged and the form submits as usual.status(flow)returns the local collection state and a stable reason, without exposing the token. Use it while debugging.
withToken again for the new request. See Device tokens.
Your API runs on a different origin
Your API runs on a different origin
The
x-abstract-device-token header makes the browser send a CORS preflight. Add the header to your API’s allowed headers, and keep an explicit list of allowed origins. With Django and django-cors-headers:Content Security Policy
Content Security Policy
Allow the Risk API origin in
script-src (the collection script) and in connect-src (token collection). If your policy uses nonces, pass nonce when you create the client.2. Backend: send a check
Your server reads the Secret key from theABSTRACT_SECRET_KEY environment variable. Pass the incoming request to the SDK: it reads the client IP, user agent, accepted language and the device token header, and nothing else. It never sends cookies, passwords, authorization headers or the request body.
Pick the pattern that matches how you’ll use the recommendation.
Observe first: send after the action
Create the account (or complete the login) first, then send the check without waiting for the answer. You review recommendations in the dashboard. This is the safest way to start, because the check can’t add latency or change what your users see.- In Python,
on_commit=transaction.on_commitsends the check only if the account write commits. A rolled-back signup sends nothing. - In Node on a serverless platform, pass a
waitUntilfunction to the constructor so the check finishes after the response. With Next.js:new Abstract({ waitUntil: (p) => after(() => p) }), usingafterfromnext/server. checkLaterreturns a local status (scheduledorskipped). It confirms the check was handed off, not that it arrived. Use Integration health to confirm delivery.
Act on the recommendation
When you’re ready to act, callcheck at the point where your handler can still change the outcome: for signup, before the new account becomes active; for login, after the password is verified and before you issue the session.
Fail-open behavior
The SDKs never throw on a Risk API problem. A timeout, network error, missing key or error response comes back as a status (skipped or failed) with a reason, and your flow continues. check waits at most 2.5 seconds in Node and 0.5 seconds in Python by default; set timeoutMs (Node) or timeout in seconds (Python) to change it.
Treat these as allow:
statusis notcompletedrecommendationisnull(no policy is configured for the flow yet)- no device token arrived (the user blocked the script, or collection was late)
Login
Login uses the same calls with"login" as the flow. Send the check after the password is verified:
Behind a proxy or load balancer
By default, a forwarded client IP (such asX-Forwarded-For) is recorded as untrusted, because callers can set that header themselves. Once you have confirmed that your load balancer overwrites the header, set trustProxy: true (Node) or trust_proxy=True (Python). If your app already knows the real client IP, pass it as ip instead.
Event IDs
Each check carries anevent_id, your correlation key for retries and for finding the check later. When you pass user.id and no eventId, the SDK uses flow:user_id. A retry with the same event ID and the same inputs returns the existing check instead of creating a new one. Generate event IDs on your server; never accept one from the browser.
3. Test without live data
Use the public test keysk_test_public_fixtures to get each response shape without sending real data. Test checks aren’t stored and don’t appear in the dashboard.
allow, review, block, device_invalid and timeout. Your own Secret key also accepts fixtures. The public test key is rate-limited and only works with a fixture. Test responses carry the X-Protection-Test-Mode: true header.
4. Verify the integration
Run the read-only doctor. It checks that the Risk API is reachable, that your Secret key works, and the health of the flow. It never prints your key.0 verified, 1 reachable but incomplete, 2 invalid local configuration, 3 service or network unavailable. A check reported as protection_unavailable means the doctor couldn’t reach the Risk API.
Then complete one real signup and one real login and open Risk Platform > Integration in the dashboard. A flow shows as verified when, within the last 24 hours, the browser SDK collected a token on an allowed origin, your backend sent a check for the same flow, that token was valid, and the client context was trusted. The same status is available from the Integration health endpoint.
Before you go live
- Confirm your exact staging and production origins are allowed for your Site key. Ask support to add any that are missing.
- Keep the Site key in browser code and the Secret key on your server only. Scan your built assets and source maps for the Secret key.
- Block the collection script in your browser and confirm signup and login still work.
- Confirm a failed or rolled-back signup sends no check.
- Confirm both flows show as verified in Integration.
- Redact the
x-abstract-device-tokenheader from your proxy, analytics and error logs.