Skip to content
v1 · beta

Zegi API

Extract text and structured data from images and PDFs — synchronously or asynchronously — with usage metering, signed webhooks and predictable, versioned responses. UAE-first, built for websites, mobile apps, ERP/POS/accounting systems and AI agents.

https://zegi.ae/api/v1

Fast & predictable

One JSON envelope, typed errors, request IDs.

Push & pull

Async jobs + signed webhooks.

AI-ready

OpenAPI 3.1 + llms.txt.

Authentication

Create a key in your API dashboard. Send it as a bearer token on every request. The key is shown once — store it securely and never expose it in client-side code or query strings.

Authorization: Bearer ajk_live_xxx.ajs_xxx
# or:
X-API-Key: ajk_live_xxx.ajs_xxx

Quick start

  1. Create an API key with the ocr:process scope.
  2. POST a file to /ocr.
  3. Read data.files[0].text from the response envelope.
curl -X POST "https://zegi.ae/api/v1/ocr" \
  -H "Authorization: Bearer $ZEGI_API_KEY" \
  -F "file=@document.png"

Every keyed response is wrapped in a consistent envelope:

{
  "success": true,
  "request_id": "req_9f2c1a7b3d4e5f60",
  "api_version": "v1",
  "data": {
    "files": [
      { "name": "document.png", "ok": true, "text": "…", "confidence": 96,
        "engine": "paddleocr", "language": "en", "document_type": "invoice",
        "structured": { /* invoice/receipt/passport when detected */ },
        "pages": [ { "page": 1, "text": "…", "confidence": 96 } ] }
    ]
  }
}

OCR

POST /ocr accepts multipart file (or files). Supported inputs: JPG, PNG, WEBP, and PDFs with a text layer. Add ?includeLayout=true for per-line bounding boxes. Recognized documents (invoice, receipt, passport) also return a typed structured object; uncertain fields are null — never fabricated.

Async jobs

For large files, submit with ?async=true to get a 202 and a job_id, then poll GET /ocr/jobs/{id}. Send an Idempotency-Key header to safely retry submissions without duplicating work.

# 1) Submit — returns 202 with a job_id
curl -X POST "https://zegi.ae/api/v1/ocr?async=true" \
  -H "Authorization: Bearer $ZEGI_API_KEY" \
  -H "Idempotency-Key: my-unique-key-001" \
  -F "file=@large.pdf"

# 2) Poll until status is "completed"
curl "https://zegi.ae/api/v1/ocr/jobs/JOB_ID" \
  -H "Authorization: Bearer $ZEGI_API_KEY"

Webhooks

Register an endpoint (POST /webhooks) to receive events. Each delivery is signed — verify the X-Zegi-Signature header (HMAC-SHA256 over `${timestamp}.${body}`) and reject timestamps older than 5 minutes. The legacy X-AjmanOCR-Signature header is still sent for backward compatibility.

Events: ocr.completedocr.failedtool.completedtool.failed

import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, headers, secret) {
  const ts = headers["x-zegi-timestamp"] ?? headers["x-ajmanocr-timestamp"]; // legacy fallback
  const sig = headers["x-zegi-signature"] ?? headers["x-ajmanocr-signature"]; // "v1=<hex>"
  const expected = "v1=" + createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // replay window
  return sig.length === expected.length && timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

Scopes

ocr:readRead OCR jobs and results.
ocr:processSubmit documents for OCR processing.
documents:readRead stored documents and their OCR results.
documents:writeCreate, update and delete stored documents.
compression:readRead compression jobs and results.
compression:processSubmit files for compression or conversion.
exports:readExport OCR results in supported formats.
usage:readRead account usage, limits and API-key status.
webhooks:readRead webhook endpoints and delivery status.
webhooks:writeCreate, update and delete webhook endpoints.
pdf:mergeMerge multiple PDFs into one.
pdf:splitSplit a PDF into pages or ranges.
pdf:convertConvert PDFs to Word/Excel.
pdf:searchableCreate searchable PDFs from images/PDFs.
image:enhanceEnhance and upscale images.

Errors

Errors use the same envelope with a stable error.code and an HTTP status. Never parse the message — switch on the code.

CodeHTTPMeaning
MISSING_API_KEY401An API key is required. Provide it as 'Authorization: Bearer <key>'.
INVALID_API_KEY401The API key is invalid.
API_KEY_REVOKED401This API key has been revoked.
API_KEY_EXPIRED401This API key has expired.
IP_NOT_ALLOWED403This API key is not permitted from your IP address.
ACCOUNT_INACTIVE403This account is not active.
INSUFFICIENT_SCOPE403This API key lacks the scope required for this operation.
API_ACCESS_NOT_ENABLED403API processing is not enabled for this account.
API_DISABLED503The API is temporarily unavailable.
WORKER_UNAVAILABLE503The processing service is temporarily unavailable.
STORAGE_UNAVAILABLE503File storage is temporarily unavailable. Please try again.
SERVICE_UNAVAILABLE503The service is temporarily unavailable.
RATE_LIMITED429Too many requests. Please slow down and retry later.
USAGE_LIMIT_EXCEEDED429Your page allowance has been reached.
INVALID_REQUEST400The request is invalid.
FILE_TOO_LARGE413The uploaded file exceeds the maximum allowed size.
UNSUPPORTED_FILE_TYPE415This file type is not supported.
INVALID_DOCUMENT422The document could not be processed.
OCR_FAILED500OCR processing failed. Please try again.
OCR_TIMEOUT504OCR processing timed out.
NOT_FOUND404The requested resource was not found.
JOB_NOT_FOUND404The requested job was not found.
CONFLICT409The request conflicts with the current state.
SERVER_ERROR500An unexpected error occurred.

Rate limits & limits

  • Max file size: 25 MB (admin-configurable).
  • Max pages processed per document: 30.
  • Page allowance & per-key rate limits depend on your plan — see GET /account.
  • 1 image = 1 page; a PDF counts its text-layer pages.
  • Rate-limited requests return 429 RATE_LIMITED; allowance exhaustion returns 429 USAGE_LIMIT_EXCEEDED.

AI integration guide

Building with an AI coding agent (Claude Code, Cursor, Lovable, Bolt, Replit, v0)? Point it at the machine-readable spec and paste this prompt. The agent will follow the real contract instead of guessing.

You are integrating the Zegi API into my application.
Read the OpenAPI specification at https://zegi.ae/api/openapi.json and follow it exactly.
Authenticate with 'Authorization: Bearer <API_KEY>'. Respect the documented scopes,
limits, error codes and the JSON response envelope. For large files submit with
?async=true and poll GET /ocr/jobs/{id}. Verify webhook signatures using the
X-Zegi-Signature header (the legacy X-AjmanOCR-Signature is also sent). Do not invent endpoints or parameters.

Machine-readable: openapi.json, openapi.yaml, llms.txt, llms-full.txt.

OpenAPI & SDKs

The full contract is published as OpenAPI 3.1. Generate a typed client in your language with any OpenAPI generator, or use the examples above directly.

# Example: generate a client from the spec
npx @openapitools/openapi-generator-cli generate \
  -i https://zegi.ae/api/openapi.json \
  -g typescript-fetch -o ./zegi-client

Changelog

v12026-08-23
  • Keyed API with API keys, scopes and usage metering
  • OCR API (sync + async jobs) with idempotency
  • Outbound webhooks with HMAC signatures + retries
  • OpenAPI 3.1, llms.txt and this documentation