API reference
One POST per submission, three answers, and reasons you can show your team.
Authentication
Send your key as a bearer token: Authorization: Bearer cv_live_…. Live keys are counted and act; test keys (cv_test_…) give fixed answers and aren’t counted: a message containing cayve-test-block is blocked, cayve-test-hold is held, anything else is allowed.
Check a submission
POST https://api.cayve.co/v1/check
{
"submission_id": "a-unique-id-per-submission",
"type": "contact",
"content": {
"name": "Dana Ruiz",
"email": "dana@example.com",
"message": "Hi, could you quote 40 cases for our two shops?"
},
"client": { "token": "valid", "javascript": true, "elapsed_ms": 48000 },
"submitter": { "ip": "203.0.113.9", "user_agent": "…" },
"context": { "site_url": "https://example.com", "integration": "my-app" }
}
type is one of contact, comment, review, registration, signup, order or other. The same submission_id sent twice returns the original decision and is counted once.
Response:
{
"id": "chk_…",
"verdict": "allow",
"score": 4,
"category": "legit",
"reasons": [],
"review": "none",
"mode": "enforce",
"engine": "2026.11.1",
"duplicate": false,
"test": false
}
verdict is allow, hold or block. reasons carry a plain and a technical text each; show them to your team, never to the person who submitted the form. mode: "shadow" means record only: don’t act on the verdict.
Tell Cayve what it was
POST /v1/feedback with { "detection_id": "chk_…", "label": "spam" } or "legit". The site learns at once.
Everything else
GET /v1/verify: is this key good, and which account and site is it for?GET /v1/usage: this month’s checks against the plan.GET /v1/detections?limit=50: recent decisions for the key’s site.GET /v1/detections/:id: one decision.
Errors come back as { "error": { "code": "…", "message": "…" } } with the matching HTTP status. Running out of your allowance is never an error: the fast checks keep answering.