Integration Guide
Protect any form or action with NexloLabs Verification in three steps. Estimated time: 5 minutes.
1. Create a site
- Open the dashboard and log in (or register).
- Go to Sites → Create site, give it a name and add your domain (e.g.
example.com). - You receive a site key (
nlx_site_...) and a site secret (nlx_secret_...). The secret is shown only once — store it in your backend environment variables.
The site secret must never be exposed in the browser. Only your backend may use it.
2. Add the widget to your page
Place this in your HTML — anywhere before the closing </body>:
<script src="https://verify.nexlolabs.net/widget.js"></script>
<div
class="nexlolabs-verification"
data-sitekey="nlx_site_YOUR_SITE_KEY"
data-type="checkbox"
data-theme="auto"
></div>
<script>
NexloLabsVerification.render(".nexlolabs-verification");
NexloLabsVerification.onSuccess((token) => {
// token is a one-time signed verification token.
// Send it with your form submission to your backend.
document.querySelector("form").dataset.verificationToken = token;
});
NexloLabsVerification.onError((error) => {
console.error("Verification failed:", error.message);
});
</script>
render()must run after the widget div is in the DOM. The widget also auto-initializes onDOMContentLoadedif the script is loaded before the container.
In your form handler (e.g. on submit), include the token:
<form id="my-form" method="POST" action="/submit">
<input type="hidden" name="verificationToken" id="verification-token" />
<!-- your fields -->
</form>
<script>
NexloLabsVerification.onSuccess((token) => {
document.getElementById("verification-token").value = token;
});
</script>
3. Verify server-side
Never trust the token from the client. In your backend, call the verify endpoint with your site secret:
POST https://verify.nexlolabs.net/api/challenge/verify
Content-Type: application/json
{
"token": "the-token-from-the-widget",
"secret": "nlx_secret_YOUR_SITE_SECRET"
}
Response:
{
"success": true,
"score": 0.97,
"challengeId": "clx9...",
"hostname": "example.com",
"expires": "2026-08-06T12:00:00.000Z"
}
| Field | Description |
|---|---|
success | true when the token is valid, unused and not expired |
score | Risk score between 0 (bot) and 1 (human) |
challengeId | The challenge that produced this token |
hostname | The origin the widget ran on (already validated) |
expires | UTC timestamp when the token expires |
Accept the submission when success is true and score is above your threshold. A sensible default is 0.5.
Full flow for a protected form
- User loads your page → widget requests a challenge from
POST /api/challenge/create(using the site key). - User solves the challenge (or passes invisibly) → widget sends the answer to
POST /api/challenge/solveand receives a token. - User submits your form → your frontend sends the token alongside the form data.
- Your backend calls
POST /api/challenge/verifywith the token and the site secret. - If verification passes, process the form. Otherwise reject with an error.