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.
When to use it
Section titled “When to use it”- 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).
How it works
Section titled “How it works”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.
Step by step
Section titled “Step by step”- Ask your site owner or the dashboard to enable assessments for the site.
- Call
createAssessmentwith the token and the action you expect. - Check
tokenProperties.validfirst, thenriskAnalysis.score. - 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'] });Request and response over HTTP
Section titled “Request and response over HTTP”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.
Annotate
Section titled “Annotate”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.
Errors
Section titled “Errors”| 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.
Security notes
Section titled “Security notes”userIpAddressmust 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.