Challenge

Getting started

Read the Botpoison Challenge docs page "Getting started": https://botpoison.com/documentation/challenge/getting-started.md
The Botpoison agent skill is at https://botpoison.com/skills/botpoison/SKILL.md.
Use them to make this change in my project, on the stack it already uses. Ask me for keys or IDs rather than inventing them.

Protect a form in three steps. The browser runs an invisible proof-of-work check before the form is sent, and your server verifies the solution.

01Add it to your form

A plain HTML form needs the script and your public key on the form. The browser runs the check when the visitor presses Send, and sends the solution with the form in the _botpoison field. A form sent with JavaScript or a framework calls challenge() and sends the solution as _botpoison itself.

HTML
<!-- 1. Import the @botpoison/browser script, pinned to one version -->
<script
src="https://unpkg.com/@botpoison/browser@1.2.0/dist/index.js"
integrity="sha384-Coq4yXcH6P37EoKbvbmZZj3UpsLwU5Ir/tth7Fgf24Q5JUj2I4hcwqtj3zKi7+PA"
crossorigin="anonymous"
async
></script>
<!-- 2. Add your public key to the data-botpoison-public-key attribute -->
<form
action="https://example.demo"
data-botpoison-public-key="pk_xxxxxxxx"
>
<input type="text" name="message" />
<button type="submit">Send</button>
</form>

If the check cannot be completed, an HTML form fires botpoison-challenge-error and is not sent, and challenge() rejects. Tell the visitor what happened. See events in the @botpoison/browser reference.

A form sent before the script loads has no solution. See before the script loads.

02Verify it on your server

Before you act on the form, send the solution to /verify with your secret key. Keep the secret key on your server, never in the browser.

npm install @botpoison/node
JavaScript
// 1. Import the library
import Botpoison from "@botpoison/node";
// or const Botpoison = require("@botpoison/node")
// 2. Create a new instance with your secret key, read from your server's
// environment: BOTPOISON_SECRET_KEY=sk_xxxxxxxx
const botpoison = new Botpoison({
secretKey: process.env.BOTPOISON_SECRET_KEY
});
server.post("/message", async (req, res) => {
const { message, _botpoison } = req.body;
// 3. Verify the solution
const { ok } = await botpoison.verify(_botpoison);
if (!ok) {
throw new Error("Invalid Botpoison solution");
}
// ...
});

The @botpoison/node reference covers verify() in full, and the REST API covers the request from any other language.

03Read the result

JSON
// The status is 200 for every result. Read "ok" to decide whether to accept
// the submission. When "ok" is false, "message" says why.
// Exceptions: 401 for two different secret keys, 413 for a body over 1 MB.
// Accepted
{ "ok": true }
// Rejected, with the reason
{ "ok": false, "message": "Invalid solution" }

Accept the form when ok is true. Otherwise, reject it. message says why.

Test key

Verify with the secret key test to try both paths without a browser. The solution ok passes and any other solution fails. Test calls never count toward your plan. See Challenge test mode.