Skip to main content

Errors

The NetraOCR API uses conventional HTTP status codes and returns a JSON body describing what went wrong.

Error shape

Failed requests return a JSON object with a detail field:

{
"detail": "File too large (Max 50MB)"
}

Validation errors (422) return a structured list identifying the offending fields:

{
"detail": [
{
"loc": ["body", "allowed_ips"],
"msg": "At least one allowed IP address is required.",
"type": "value_error"
}
]
}

Always branch on the HTTP status code first; use detail for logging and user-facing messages.

Status codes

CodeNameMeaning & typical fix
200OKSuccess.
201CreatedResource created (e.g. an API key).
202AcceptedAsync work accepted (bulk upload); poll for results.
400Bad RequestMalformed input — e.g. invalid Base64. Fix the request.
401UnauthorizedMissing/invalid credentials. Check your api_key/api_secret.
403ForbiddenIP not on the key's allow-list, or a plan limit reached.
402Payment RequiredAccount cannot process the request. Review access in the console and retry.
404Not FoundUnknown job_id, template, or resource — or not owned by you.
413Payload Too LargeFile exceeds the size limit (50 MB single / 600 MB bulk).
422Unprocessable EntityValidation failed; inspect the detail list.
429Too Many RequestsRate limit exceeded. Back off and retry. See Rate Limits.
5xxServer ErrorTransient server issue. Retry with backoff; contact support if it persists.

Handling errors well

  • Authentication (401/403). Verify credentials and confirm the calling host's public IP is on the key's allow-list — use GET /api-keys/my-ip to check.
  • Payment required (402). Review account access in the console or estimate bulk work with bulk-analyze.
  • Rate limits (429). Implement exponential backoff. See Rate Limits.
  • Server errors (5xx). Retry idempotent reads freely. For uploads, check job status before re-submitting to avoid duplicate charges.

Example: robust upload

import time, requests

def upload(path, template_id, **params):
for attempt in range(4):
r = requests.post(
"https://netraocr.shivicx.com/api/v1/ocr/upload",
auth=("ak_live_xxxxxxxx", "sk_live_xxxxxxxx"),
files={"file": open(path, "rb")},
params={"template_id": template_id, **params},
)
if r.status_code == 429 or r.status_code >= 500:
time.sleep(2 ** attempt) # back off and retry
continue
r.raise_for_status() # raise on other 4xx
return r.json()
raise RuntimeError("Upload failed after retries")