Docs

Send a page. Get the text back.

The Kindi Labs API runs the same models as the playground. Send an image, wait for the job, read the result.

Base URLhttps://api.asnb.sa/v1

Quickstart

  1. 1

    Create an account

    Sign up and confirm your email.

    Create an account
  2. 2

    Create an API key

    In your account, under API keys. Copy it when it's shown: it isn't shown again.

    API keys
  3. 3

    Send a page

    Post an image to /v1/jobs, then read the job until it's done.

Authentication

Send your key in the Authorization header on every request. Keep keys on your server: never put one in a web page or a mobile app. You can revoke a key at any time in your account.

Authorization: Bearer asnb_live_…

Send a page

Post the image as multipart form data with the model to use. The API answers at once with a job in the queue.

POST/v1/jobs

Fields
FieldMeaning
modelasnb-ocr for printed Arabic, asnb-htr for handwriting.
fileThe page image: PNG, JPEG or WebP.
curl https://api.asnb.sa/v1/jobs \
  -H "Authorization: Bearer $KINDI_API_KEY" \
  -F model=asnb-ocr \
  -F [email protected]

Read the result

Read the job until its status is succeeded or failed. Waiting a second or two between reads is plenty.

GET/v1/jobs/{id}

curl https://api.asnb.sa/v1/jobs/job_8f2k1x9q3m7d \
  -H "Authorization: Bearer $KINDI_API_KEY"

An example response for one of the sample pages (a 1899 magazine page), shortened. Confidence values are for illustration.

{
  "job": {
    "id": "job_8f2k1x9q3m7d",
    "model": "asnb-ocr",
    "model_version": "v1.0",
    "status": "succeeded",
    "created_at": "2026-10-09T09:41:12Z",
    "finished_at": "2026-10-09T09:41:15Z",
    "file": {
      "name": "muqtataf-1899.jpg",
      "type": "image/jpeg",
      "size": 204803
    },
    "error": null,
    "result": {
      "text": "فقلنا وهل تدّعي ان الآلة التي تشير اليها ترفع الماء من نفسها من غير قوة تساعدها على رفعه.\nفقال كلاً بل اننا نضع ماءً في جانب منها فتدور به وتغرف الماء من النيل وترفعه. فقلنا ومن اين\n…",
      "pages": [
        {
          "index": 0,
          "width": 940,
          "height": 772,
          "lines": [
            {
              "text": "فقلنا وهل تدّعي ان الآلة التي تشير اليها ترفع الماء من نفسها من غير قوة تساعدها على رفعه.",
              "bbox": [8, 106, 920, 43],
              "confidence": 0.98
            },
            {
              "text": "فقال كلاً بل اننا نضع ماءً في جانب منها فتدور به وتغرف الماء من النيل وترفعه. فقلنا ومن اين",
              "bbox": [8, 155, 920, 44],
              "confidence": 0.96
            }
          ]
        }
      ]
    }
  }
}

The job object

FieldMeaning
idThe job's ID.
model, model_versionWhich model read the page, and which version.
statusqueued, running, succeeded or failed.
created_at, finished_atWhen the job was created and finished (ISO 8601, UTC).
fileThe name, type and size you uploaded.
errorWhen failed: a code and a message.
result.textAll the text, one line per line, pages separated by a blank line.
result.pages[].lines[]Each line's text, its box [x, y, width, height] in the image's pixels, and a confidence from 0 to 1.

Errors

Errors come back with an HTTP status and a JSON body. Use the code, not the message, in your own logic.

{ "error": { "code": "file_too_large", "message": "The file is over 10 MB." } }
HTTPcodeMeaning
401unauthorizedThe key is missing, wrong, or revoked.
400invalid_requestA field is missing or the model is unknown.
413file_too_largeThe file is over the size limit.
415unsupported_typeThe file isn't PNG, JPEG or WebP.
403quota_exceededThis month's pages are used up.
404not_foundNo such job on your account.
429rate_limitedToo many requests. Wait for Retry-After seconds.
500server_errorSomething failed on our side. Try again.

Limits

Images up to 10 MB, in PNG, JPEG or WebP. Each image counts as one page. Your monthly pages and what you've used are shown in your account.

Models

modelNameFor
asnb-ocrKindi OCR v1.0Printed Arabic: newspapers, books, documents.
asnb-htrKindi HTR v0.12Handwritten Arabic in five scripts. In development.

Try it in the playground firstHow the models score