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.