Skip to content

Assessments and annotations

An assessment is an alternative to siteverify that returns a richer answer, in the shape of reCAPTCHA Enterprise’s assessments. You can annotate it later with what really happened, which teaches the scorer.

  • You want account labels, MFA, payment or SMS fraud scoring (they all ride on assessments).
  • You are moving from reCAPTCHA Enterprise and want the same response shape.
  • You want to score an IP address with no token (an express assessment).

For a plain yes or no on a form, siteverify is enough. An assessment is off for a site until its flags are set (a closed flag is 403 feature-disabled).

A token assessment verifies the token (one use, shared with siteverify) and returns the score and reasons. An invalid token is still a 200, with tokenProperties.valid: false, an invalidReason and a score of 0. An express assessment (express: true, no token) scores userIpAddress alone: its scores are only 0.1, 0.3, 0.5 or 0.7, and it always carries LOW_CONFIDENCE_SCORE.

  1. Ask your site owner or the dashboard to enable assessments for the site.
  2. Call createAssessment with the token and the action you expect.
  3. Check tokenProperties.valid first, then riskAnalysis.score.
  4. Keep name (assessments/<aid>). When you learn the truth, annotate.
const a = await rg.createAssessment({ token, expectedAction: 'login' });
if (a.tokenProperties.valid && a.riskAnalysis.score >= 0.5) allow();
await rg.annotate(a.name, { annotation: 'FRAUDULENT', reasons: ['CHARGEBACK'] });
Terminal window
curl https://api.revokegpt.com/v1/assessments \
-H 'Authorization: Bearer rgsk_...' -H 'Content-Type: application/json' \
-d '{"event":{"token":"<token>","expectedAction":"login","userIpAddress":"203.0.113.7"}}'
{
"name": "assessments/<42 characters>",
"riskAnalysis": { "score": 0.9, "reasons": [] },
"tokenProperties": { "valid": true, "createTime": "2026-11-15T10:00:00Z", "hostname": "shop.example", "action": "login" },
"event": { "expectedAction": "login", "express": false }
}

invalidReason is one of MALFORMED, EXPIRED, DUPE, MISSING, UNEXPECTED_ACTION, KEY_MISMATCH, DOMAIN_MISMATCH. Other blocks (accountDefenderAssessment, requiresMfa, accountVerification, fraudPreventionAssessment, phoneFraudAssessment) appear only when they apply. Tolerate fields you do not know.

POST /v1/assessments/{id}:annotate accepts annotation (LEGITIMATE or FRAUDULENT), reasons, accountId or hashedAccountId, and transactionEvent. It answers 200 with an empty object. Annotate with ground truth you learn later (a chargeback, a confirmed fraudulent signup, a legitimate purchase), not guesses. A different label replaces the earlier one.

Status and code Meaning What to do
400 bad-request Invalid body, a query string, an Origin header, or a card number in transactionData. Fix the request.
401 unauthorized Missing or wrong secret, a management key, or a disabled site (one uniform answer). Check the secret.
402 plan-required / plan-restricted Billing. See billing.
403 feature-disabled The site has not enabled this feature. Enable it or stop calling it.
404 not-found Unknown assessment, wrong site or altered id. Use the name you were given.
410 expired The assessment is older than 30 days. Too late to annotate.
413, 415 Body too large, or not application/json. Fix the request.
429 rate-limited Too many calls. Retry-After: 1. Wait and retry.
503 service-unavailable Assessments are off or unavailable. Siteverify is unaffected. Fall back to siteverify or your own policy.

SDKs throw on these (Node: RevokeGPTError with code and status); see your SDK reference.

  • userIpAddress must be the real end-user address. Behind a proxy, configure your framework’s proxy trust.
  • The score model, the rules that fired and the thresholds behind a label are never returned.
  • Keep the secret on the server. Body limits: 8 KiB for assessments, 2 KiB for annotations.

The endpoints are POST /v1/assessments and POST /v1/assessments/{id}:annotate; see the reference.