API guide
Using the API
A JSON-over-HTTPS API at https://captchaocr.allvoraz.com. This page covers everything you need. The API reference has the same material as an OpenAPI spec with a try-it console.
Endpoints
| Method | Path | Does |
|---|---|---|
POST | /v1/solve | Solve one captcha |
POST | /v1/solve_batch | Solve up to 256 captchas in parallel |
GET | /v1/balance | Credits left |
POST | /v1/report | Report a wrong answer and get the credit back |
GET | /health | Service status (no key needed) |
POST | /createTask … | Task API: createTask, getTaskResult, getBalance, reportIncorrect |
Authentication
Every /v1 call needs an API key from Dashboard → API keys. Send it as Authorization: Bearer <key> (preferred) or X-API-Key: <key>. Keys start with co_live_. Only a hash is stored, so a lost key can't be recovered: revoke it and create a new one. Revoked keys stop working within 30 seconds. Keep keys on your servers. Never ship them in a browser or mobile app.
Solve a captcha: POST /v1/solve
curl -s https://captchaocr.allvoraz.com/v1/solve \
-H "Authorization: Bearer $CAPTCHA_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"image\": \"$(base64 < captcha.png | tr -d '\n')\", \"numeric\": true, \"length\": 6}"Request body
| Field | Type | Meaning |
|---|---|---|
image | string, required | Base64 image: PNG, JPEG, GIF, WebP, TIFF, BMP or SVG, detected by content. A data:image/…;base64, prefix is fine. Up to 5 MB. |
numeric | boolean | The captcha may contain digits 0-9. |
uppercase | boolean | May contain A-Z. Alone, lowercase readings are folded to uppercase. |
lowercase | boolean | May contain a-z. Alone, uppercase readings are folded to lowercase. |
length | integer 1-32 | Exact number of characters. The decoder returns the most likely reading of that length. Ignored with math. |
math | boolean | Arithmetic captcha (“14 - 10 = ?”); text is the computed answer. |
hindi | boolean | Operands are Hindi number words (“इकतीस + 6 = ?”). Requires math. |
With none of numeric, uppercase or lowercase set, digits and both cases are allowed and case is kept as read. Unknown fields are rejected (422), so typos don't pass silently.
Response
| Field | Type | Meaning |
|---|---|---|
text | string | What to type. For math captchas, the computed answer. |
reliable | boolean | Submit only when true. Only reliable answers are charged. |
confidence | number 0-1 | Probability of the least certain character. |
engine | ocr | math | hindi_math | Which engine read the image. |
raw | string | The model's reading before post-processing (e.g. इकतीस+6). |
expression | string | null | Math only: what was computed, e.g. 31+6. |
error | string | null | invalid_image (undecodable, not charged), model_unavailable, internal_error. |
id | integer | Task id, for /v1/report (kept 48 hours). |
charged | boolean | Whether this answer cost a credit. |
The X-Credits-Remaining response header carries your balance after the call.
Choosing options
Describe the captcha, not the answer you want. Each option rules out readings the model could otherwise make, which raises accuracy:
| Captcha looks like | Send |
|---|---|
| 482915: always 6 digits | {"numeric": true, "length": 6} |
| 14 + 9 = ? (answer: 23) | {"math": true} |
| PUKLX8: capitals and digits | {"uppercase": true, "numeric": true} |
| hyi5ag: the site ignores case | {"lowercase": true, "numeric": true} |
| 7rX2Yx: mixed case, case matters | nothing (case is kept as read) |
| बयालीस - 6 = ? (answer: 36) | {"math": true, "hindi": true} |
numericalone also turns look-alike letters into digits (O→0,l→1,S→5,B→8).uppercaseorlowercasealone folds the other case in, and turns look-alike digits into letters.lengthis enforced by the decoder itself. Set it whenever a site's captchas have a fixed length.
Acting on the result
if res.error: # undecodable image: re-download it (not charged)
...
elif res.reliable: # submit res.text (charged: 1 credit)
...
else: # unsure: refresh the captcha and solve the new one (not charged)
...reliable combines the confidence with engine-specific checks: the length matched, a math answer is non-negative, a Hindi number word was read exactly. Refreshing a doubtful captcha is cheaper than a failed form submission, which can cost a page reload or a lockout.
Batches: POST /v1/solve_batch
Up to 256 images, solved in parallel, returned in request order. Top-level options apply to every image, and any item can override them. A plain base64 string works as shorthand for {"image": "…"}. A bad image fails only its own slot.
b64() { base64 < "$1" | tr -d '\n'; }
curl -s https://captchaocr.allvoraz.com/v1/solve_batch \
-H "Authorization: Bearer $CAPTCHA_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"numeric\": true, \"images\": [
{\"image\": \"$(b64 a.png)\"},
{\"image\": \"$(b64 b.png)\", \"length\": 5},
{\"image\": \"$(b64 sum.png)\", \"math\": true}
]}"Credits for the whole batch are reserved before solving (402 if the balance can't cover it), and the unreliable ones are returned before the response is sent.
Submit now, fetch later: POST /v1/submit + GET /v1/result/{id}
/v1/solve answers in the same request. When you'd rather not hold the connection (queues, workers, clients with short timeouts), submit the captcha instead. POST /v1/submit takes the same body and options, reserves a credit, and returns {"id": 184467, "status": "processing"} (HTTP 202) immediately. The captcha is solved in the background, usually within 0.1 s.
# Returns at once with a task id; the captcha is solved in the background.
curl -s https://captchaocr.allvoraz.com/v1/submit -H "Authorization: Bearer $CAPTCHA_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"image\": \"$(base64 < captcha.png | tr -d '\n')\", \"numeric\": true, \"length\": 6}"
# {"id": 184467, "status": "processing"}
# Fetch the answer; wait=10 holds the request until it's ready (up to 10 s).
curl -s "https://captchaocr.allvoraz.com/v1/result/184467?wait=10" -H "Authorization: Bearer $CAPTCHA_API_KEY"
# {"id": 184467, "status": "ready", "result": {"text": "482915", "reliable": true, ...}, "error": null}GET /v1/result/{id} returns the task:
| status | Meaning |
|---|---|
processing | Not finished. Ask again in about half a second, or pass ?wait=N. |
ready | result holds the answer: the same object /v1/solve returns. Check result.reliable. |
failed | The solver couldn't run; error says why. The credit was returned. Submit again. |
Add ?wait=10 (0-30 seconds) and the request returns the moment the answer is ready, so one call usually does it with no polling loop. Without it, poll:
# Without wait: "processing" until the answer is ready, then "ready" (or "failed").
curl -s https://captchaocr.allvoraz.com/v1/result/184467 -H "Authorization: Bearer $CAPTCHA_API_KEY"
# {"id": 184467, "status": "processing", "result": null, "error": null}Billing is identical to /v1/solve: unreliable and undecodable results are refunded when the task finishes, and the task id works with /v1/report. Results are kept 48 hours. Each key can have up to 256 unfinished tasks (429 beyond that); another key's task ids return 404.
Billing, balance and refunds
- 1 credit = 1 reliable answer. Undecodable images and low-confidence reads are free.
- Buy credit packs on the billing page with UPI (Google Pay, PhonePe, Paytm), cards, netbanking or wallets. Credits never expire. See pricing.
GET /v1/balancereturns{"credits": N, "alert_threshold": T}(alert_thresholdis null without an alert). Every solve response also carries the balance inX-Credits-Remaining:
curl -s https://captchaocr.allvoraz.com/v1/balance -H "Authorization: Bearer $CAPTCHA_API_KEY"
# {"credits": 4321}Low-balance alert: PUT /v1/alert
Each account can have one alert. When a solve leaves your credits below its threshold, we POST your JSON payload to your HTTPS url with your headers, so you top up before captchas start failing with 402.
# One alert per account. When your credits drop below 500, we POST the payload to your URL.
curl -s -X PUT https://captchaocr.allvoraz.com/v1/alert -H "Authorization: Bearer $CAPTCHA_API_KEY" \
-H 'Content-Type: application/json' -d '{
"threshold": 500,
"url": "https://hooks.example.org/captcha-credits",
"payload": {"text": "Captcha credits low: {{credits}} left (alert at {{threshold}})"},
"headers": {"Authorization": "Bearer my-hook-secret"}
}'
# {"threshold": 500, "url": "...", "armed": true, "last_status": null, ...}
curl -s -X POST https://captchaocr.allvoraz.com/v1/alert/test -H "Authorization: Bearer $CAPTCHA_API_KEY"
# {"delivered": true, "status": 200, "error": null}
curl -s https://captchaocr.allvoraz.com/v1/alert -H "Authorization: Bearer $CAPTCHA_API_KEY" # read it
curl -s -X DELETE https://captchaocr.allvoraz.com/v1/alert -H "Authorization: Bearer $CAPTCHA_API_KEY" # remove it| Field | Meaning |
|---|---|
threshold | Fire when credits drop below this (1 or more). |
url | Your HTTPS endpoint; it must resolve to a public address. Redirects are not followed. |
payload | Optional JSON object, up to 8 KB. {{credits}}, {{threshold}} and {{time}} are filled in; a value that is exactly "{{credits}}" becomes a number. Default: {"event": "low_balance", "credits": N, "threshold": T}. |
headers | Optional, up to 10, e.g. Authorization, so your endpoint can verify the call. |
- It fires once per drop below the threshold (
armedbecomes false) and re-arms when a purchase brings your balance back to the threshold or above. - Any 2xx answer counts as delivered; otherwise we retry after 10 s and 60 s. Requests carry
X-CaptchaOCR-Event: low_balance. GET /v1/alertshows the alert and its last delivery,DELETE /v1/alertremoves it, andPOST /v1/alert/testsends it now (without disarming it) and returns what your endpoint answered.
If a site rejects a reliable answer, send its id to POST /v1/report within 48 hours and the credit comes back. Refunds per day are capped at 10% of that day's charged solves, plus 5. The response says refunded, and if not, a reason: already_reported, not_charged, unknown_task or daily_refund_limit.
curl -s https://captchaocr.allvoraz.com/v1/report -H "Authorization: Bearer $CAPTCHA_API_KEY" \
-H 'Content-Type: application/json' -d '{"id": 184467}'
# {"refunded": true, "reason": null, "credits": 4322}Errors
Errors are JSON: {"detail": "…"}, plus credits on 402. Every SDK raises an API exception carrying the status and body. A bad image is not an error: it's a normal 200 result with error set.
| Status | Meaning | What to do |
|---|---|---|
200 + error: invalid_image | The image can't be decoded. | Not charged. Re-download the captcha. |
401 invalid_api_key | Missing, wrong or revoked key. | Check Authorization / X-API-Key. |
402 insufficient_credits | Balance can't cover the request; body has credits. | Buy credits on the dashboard. |
422 | Invalid options: unknown field, hindi without math, length out of 1-32, 0 or >256 images. | Fix the request; don't retry. |
404 unknown_task / no_alert | GET /v1/result: no such task for this key, or older than 48 hours. /v1/alert: none set. | Check the id; submit again. Set an alert first. |
429 too_many_concurrent_requests | More than 32 requests in flight, or 256 unfinished submitted tasks, on one key. | Retry after the Retry-After header. |
503 solver_unavailable | Temporary problem; credits were returned. | Retry with exponential backoff. |
Limits and performance
- About 25 ms per text captcha and 6 ms per math captcha, plus network time.
- 32 concurrent requests and 256 unfinished submitted tasks per key (429 beyond that), 256 images per batch, 5 MB per image.
- Reuse one HTTP client or SDK client: keep-alive saves a TLS handshake on every call.
- Results are kept 48 hours for
/v1/resultand reports, then deleted. Images are not stored.
Accuracy
Measured on real captchas from Indian government portals. None of these images were used for training, unless noted.
| Captcha | Sample | Answers correct |
|---|---|---|
| Hindi-number arithmetic (state land-records portal) | 175 live captchas, never trained on | 100% |
| Arithmetic (state land-records portal) | 120 live captchas | 95.0%; of answers marked reliable, 98.3% |
| Text captchas, 46 government sites | 465 captchas, compared with human-verified answers | 88.0% agreement (88.6% with length/numeric set) |
For text captchas, 87.5% of answers are marked reliable, and 92.6% of those match the reference answer. Several mismatches are mistakes in the reference itself, so real precision is higher. Accuracy varies by site: test on your captchas with the free credits before you scale up.
Versioning
The API and every SDK share one semantic version (now 1.0.0). Adding fields is a minor release, and clients must ignore unknown response fields. Removing or renaming a field would be a new major version under a new path.