דילוג לתוכן

תיעוד API

ה-API של OCR-AI

קריאה של PDF ותמונות לטקסט, שדות וטבלאות, מלקוח MCP או ב-HTTPS רגיל. הדוגמאות והשמות כאן באנגלית, כמו בקוד.

כתובת בסיס
https://ocr-ai.com
MCP
https://ocr-ai.com/mcp
Markdown
https://ocr-ai.com/docs.md
01הסוכן קורא לכלי02שדות חוזרים, עמודים נספרים03נגמרו העמודים: קישור תשלום, בלי חיוב

01הרשאה

כל קריאה שקוראת או סופרת עמודים צריכה מפתח API, בכותרת ⁦Authorization: Bearer ocrai_sk_…⁩ (או ⁦X-API-Key: ocrai_sk_…⁩).

יוצרים מפתחות בעמוד החשבון, אחרי שמבקשים גישה בעמוד הסוכנים. מפתח מוצג פעם אחת, כשיוצרים אותו, ואפשר לבטל אותו שם בכל רגע. שמרו מפתחות בצד השרת: לא בדף אינטרנט ולא באפליקציה לטלפון.

02MCP

נקודת הקצה: ⁦/mcp⁩, בתעבורת Streamable HTTP. השרת לא שומר מצב: כל POST מקבל תשובת JSON אחת, בלי סשן ובלי זרם אירועים. גרסאות הפרוטוקול הנתמכות: 2025-11-25, 2025-06-18, 2025-03-26 ו-2024-11-05.

initialize ו-tools/list עובדים בלי מפתח; tools/call צריך מפתח. בעיות שמודל יכול לטפל בהן (אין מפתח, אין מספיק עמודים, ארגומנט שהכלי לא מקבל, קובץ שאי אפשר לקרוא) חוזרות כתוצאת כלי עם isError: true, משפט למודל וקוד שגיאה ב-structuredContent.

בקשות בלי כותרת Origin, ובקשות מכל מקור https, מתקבלות: מפתח ה-API הוא ההרשאה היחידה. דף ממקור null, file: או http רגיל, או מכל סכמה אחרת, נדחה ב-403, גם בבדיקת ה-CORS המקדימה.

קריאה של הרבה עמודים יכולה לקחת יותר מדקה. לקוחות MCP מפסיקים לחכות אחרי זמן קבוע (60 שניות כברירת מחדל ב-SDK של MCP ל-TypeScript): הגדילו אותו ל-read_document, או קראו פחות עמודים בכל קריאה. קריאה שהחיבור שלה נסגר לפני שהתשובה נשלחה מזוכה במלואה; עמודים שלקוח הפסיק לחכות להם בזמן שהחיבור נשאר פתוח מחויבים.

כליארגומנטיםמחזיר
read_documentfile_url או file_base64 (אחד מהם); pages, למשל "1-5,8"; hint: ⁦auto, invoice, receipt, card, table, text⁩ (card הוא כרטיס ביקור); language של התוויות והתקציר: en או heטקסט Markdown, ו-structuredContent: אובייקט המסמך
check_balanceאיןbalance, expired, buy_url, packs
buy_pagespack: p100, p500, p2000; currency: USD (ברירת מחדל) או ILSbuy_url לחבילה, עם מספר העמודים והמחיר
mcp.json
{
  "mcpServers": {
    "ocr-ai": {
      "type": "http",
      "url": "https://ocr-ai.com/mcp",
      "headers": {
        "Authorization": "Bearer ocrai_sk_…"
      }
    }
  }
}
קריאה לכלי, בלי לקוח MCP
curl https://ocr-ai.com/mcp \
  -H "Authorization: Bearer ocrai_sk_…" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call",
       "params": {"name": "read_document",
                  "arguments": {"file_url": "https://example.com/invoice.pdf"}}}'

03REST

POST/api/v1/read

שולחים את המסמך באחת משלוש דרכים:

  • multipart/form-data עם שדה קובץ בשם file, ושדות רשות pages, hint ו-language;
  • application/json עם file_base64 או file_url (קישור https ציבורי), ושדות רשות pages, hint ו-language;
  • הקובץ עצמו, עם ה-Content-Type שלו (application/pdf, image/jpeg, image/png או image/webp), והאפשרויות כפרמטרים בכתובת.

התשובה היא אובייקט המסמך. סוג הקובץ נקבע לפי הבייטים שלו, לא לפי השם או הסוג שהוצהר.

השדות והפרמטרים נבדקים: שדה שהקריאה לא מכירה, ערך מסוג לא נכון, או hint או language מחוץ לרשימה שלהם, עונים 400 bad_request, וההודעה אומרת איזה.

כל הבדיקות נעשות לפני שהתשובה מתחילה. אחר כך הסטטוס 200 נשלח מיד, והגוף כשהקריאה מסתיימת. אם הקריאה נכשלת אחרי זה, הגוף נקטע במקום להגיע כ-JSON חלקי, וכל העמודים של הקריאה חוזרים לחשבון. גם מי שמתנתק לפני שהגוף נשלח מקבל את העמודים בחזרה.

העלאת קובץ
curl https://ocr-ai.com/api/v1/read \
  -H "Authorization: Bearer ocrai_sk_…" \
  -F "file=@invoice.pdf" \
  -F "pages=1-3"
קובץ לפי קישור
curl https://ocr-ai.com/api/v1/read \
  -H "Authorization: Bearer ocrai_sk_…" \
  -H "Content-Type: application/json" \
  -d '{"file_url": "https://example.com/invoice.pdf", "hint": "invoice"}'
הקובץ עצמו
curl "https://ocr-ai.com/api/v1/read?pages=1-3&language=he" \
  -H "Authorization: Bearer ocrai_sk_…" \
  -H "Content-Type: application/pdf" \
  --data-binary @invoice.pdf

GET/api/v1/balance

כמה עמודים נשארו בחשבון של המפתח, האם עמודים שלא נוצלו פגו, והחבילות, כל אחת עם buy_url. עם הפרמטר ⁦language=he⁩ בכתובת, הקישורים פותחים את העמוד בעברית והמחירים בשקלים.

יתרה
curl https://ocr-ai.com/api/v1/balance \
  -H "Authorization: Bearer ocrai_sk_…"

04אובייקט המסמך

שדהמשמעות
object"document"
total_pagesמספר העמודים בקובץ.
pages_readעמודים שנקראו בקריאה הזו.
pages_chargedעמודים שחויבו בקריאה הזו. עמודים שנכשלו לא מחויבים.
balanceהעמודים שנשארו בחשבון אחרי הקריאה.
next_pagesטווח העמודים לקריאה הבאה, כשבקובץ יש יותר עמודים ממה שקריאה אחת קוראת; אחרת null.
buy_urlמופיע כשנגמרו העמודים בחשבון: המקום שבו אדם יכול להוסיף.
pages[]רשומה לכל עמוד שנקרא, לפי הסדר: page, status (done, failed או no_pages), ובעמוד שנקרא גם partial, document_type, language, summary, fields, tables ו-text.

לכל שדה יש key, label, value ו-type, וכשרלוונטי גם normalized (תאריך כ-YYYY-MM-DD, סכומים ומספרים כמספר עשרוני פשוט), box ([ymin, xmin, ymax, xmax], בין 0 ל-1000 ביחס לעמוד) ו-uncertain (true כשהערך היה קשה לקריאה).

לכל טבלה יש columns ו-rows (מערך תאים לכל שורה), וכשידוע גם title ו-box.

דוגמת תשובה (מקוצרת)
{
  "object": "document",
  "total_pages": 1,
  "pages_read": 1,
  "pages_charged": 1,
  "balance": 99,
  "next_pages": null,
  "pages": [
    {
      "page": 1,
      "status": "done",
      "partial": false,
      "document_type": "invoice",
      "language": "he",
      "summary": "חשבונית מס 20417 מסטודיו תמר לקפה נמל, על סך 6,018.00 ₪ כולל מע״מ.",
      "fields": [
        {
          "key": "document_number",
          "label": "מספר חשבונית",
          "value": "20417",
          "type": "id",
          "box": [
            124,
            743,
            143,
            798
          ]
        },
        {
          "key": "issue_date",
          "label": "תאריך הפקה",
          "value": "21/10/2026",
          "normalized": "2026-10-21",
          "type": "date",
          "box": [
            144,
            706,
            163,
            798
          ]
        },
        {
          "key": "total",
          "label": "סה״כ לתשלום",
          "value": "6,018.00 ₪",
          "normalized": "6018",
          "type": "money",
          "box": [
            595,
            86,
            618,
            202
          ]
        }
      ],
      "tables": [
        {
          "title": "פירוט החשבונית",
          "columns": [
            "#",
            "תיאור",
            "כמות",
            "מחיר יחידה",
            "סה״כ"
          ],
          "rows": [
            [
              "1",
              "עיצוב שלט חזית",
              "1",
              "2,400.00",
              "2,400.00"
            ],
            [
              "2",
              "הדפסה על לוח אלומיניום 120×60",
              "2",
              "680.00",
              "1,360.00"
            ]
          ],
          "box": [
            349,
            73,
            516,
            928
          ]
        }
      ],
      "text": "סטודיו תמר — שילוט ועיצוב גרפי בע״מ\nרח׳ הנגב 12, באר שבע · טל׳ 08-6230145\n…"
    }
  ]
}

05ERP ו-CRM

המפתחות ב-fields קבועים: אותו שדה מגיע תמיד באותו מפתח, ולכן ממפים אותם פעם אחת לשדות של ה-ERP או ה-CRM. ערך המכונה נמצא ב-normalized: תאריך בצורה YYYY-MM-DD וסכום כמספר עשרוני.

תהליך ב-Make, n8n, Zapier או Power Automate: צעד HTTP שולח את המסמך ל-⁦POST /api/v1/read⁩, ממפה את fields ואת tables, ויוצר את הרשומה במערכת. ערך עם ⁦uncertain: true⁩ יכול לעצור לבדיקה של אדם.

מפתחותברשומה במערכת
vendor_name, vendor_tax_id, vendor_addressהספק, או חשבון ספק ב-ERP.
document_number, allocation_number, issue_date, due_dateכותרת המסמך: מספר, מספר הקצאה ותאריכים.
subtotal, discount, vat_rate, vat_amount, total, currencyסכומי המסמך.
tables[0].rowsשורות הפריטים.
full_name, job_title, company, email, phone, mobile, fax, website, addressאיש קשר או ליד ב-CRM. בכרטיס ביקור, document_type הוא business_card

בסביבת העבודה אותם נתונים יורדים גם כקבצים: קובץ ל-ERP וקובץ ל-CRM עם עמודות קבועות, ו-vCard. רשימות העמודות בעמוד האינטגרציות

06עמודים ותשלום

  • עמוד ב-PDF, או תמונה אחת, הם עמוד אחד. עמוד מחויב כשהוא נקרא; אם הקריאה נכשלה, העמוד חוזר והרשומה שלו מסומנת ⁦status: "failed"⁩ ו-refunded: true.
  • קריאה נבדקת לפני שמשהו נקרא. כשיש בחשבון פחות עמודים ממה שהקריאה צריכה, התשובה היא 402 payment_required, עם needed, balance, total_pages, buy_url ו-packs. שום דבר לא נקרא ושום דבר לא מחויב.
  • buy_url פותח את עמוד הוספת העמודים של המפתח, שבו בוחרים חבילה; ה-buy_url של כל חבילה, ב-packs, פותח Stripe Checkout לחבילה הזו ישירות. התשלום מוסיף את העמודים לחשבון של המפתח. הוא לא מחבר אף אחד ולא נותן גישה לחשבון, ולכן בטוח למסור את הקישורים למי שמשלם. בקריאה עם ⁦language: "he"⁩, העמוד בעברית והמחירים בשקלים.
  • חשבון חדש מקבל 100 עמודים חינם עם המפתח הראשון. אם ההתחלות החינמיות של היום נגמרו, העמודים נוספים בקריאה או בבדיקת יתרה ביום אחר. העמודים בתוקף 12 חודשים מהפעם האחרונה שנוספו לחשבון עמודים, ברכישה או בהתחלה החינמית.
תשובת 402
{
  "error": "payment_required",
  "message": "This call reads 4 pages; the key's account has 3. Ask your user to add pages at buy_url, or read fewer pages with \"pages\".",
  "needed": 4,
  "balance": 3,
  "total_pages": 4,
  "buy_url": "https://ocr-ai.com/en/topup?key=key_7Hq2mXc9Lp0a",
  "packs": [
    {
      "pack": "p100",
      "pages": 100,
      "price": 9,
      "currency": "USD",
      "buy_url": "https://ocr-ai.com/api/v1/buy?key=key_7Hq2mXc9Lp0a&pack=p100&currency=USD"
    },
    {
      "pack": "p500",
      "pages": 500,
      "price": 29,
      "currency": "USD",
      "buy_url": "https://ocr-ai.com/api/v1/buy?key=key_7Hq2mXc9Lp0a&pack=p500&currency=USD"
    },
    {
      "pack": "p2000",
      "pages": 2000,
      "price": 89,
      "currency": "USD",
      "buy_url": "https://ocr-ai.com/api/v1/buy?key=key_7Hq2mXc9Lp0a&pack=p2000&currency=USD"
    }
  ]
}

07מגבלות

  • עד 20 עמודים בקריאה, עד 20MB לקובץ, ועד 28MB לגוף הבקשה, כך שגם קובץ של 20MB ב-base64 נכנס.
  • קובץ PDF יכול להכיל עד 5000 עמודים בסך הכול; ארוך יותר נדחה כולו (422 too_many_pages). עמוד שגדול מ-8MB אחרי שהוצא מה-PDF נכשל ולא מחויב (page_too_large).
  • בערך 30 קריאות בדקה למפתח; מעבר לזה, 429 rate_limited.
  • file_url חייב להיות קישור https ציבורי: בלי שם משתמש או סיסמה, בלי כתובת IP ובלי שם שרת פנימי. מותרות עד 3 הפניות, וכל כתובת בדרך נבדקת באותו כלל. ההורדה צריכה להסתיים תוך 20 שניות.
  • העמודים נקראים כמה במקביל, ובכל זאת קריאה של הרבה עמודים יכולה לקחת יותר מדקה: תנו לבקשה מספיק זמן, או קראו פחות עמודים בכל קריאה.

08שגיאות

לכל תשובת שגיאה יש error, קוד קבוע, ו-message, משפט שמודל יכול להעביר למשתמש. חלקן מוסיפות פרטים: get_key_url ב-401, שדות התשלום ב-402, ו-max_pages ב-too_many_pages.

HTTPerrorמתי
400bad_requestאי אפשר לקרוא את הגוף או שהוא לא אובייקט JSON, או ששדה או פרמטר לא מוכר, מסוג לא נכון או מחוץ לערכים המותרים. ההודעה אומרת איזה.
400missing_fileאין שדה multipart בשם file, או שאין file_base64 וגם לא file_url.
400bad_base64file_base64 הוא לא base64 תקין.
400bad_urlfile_url הוא לא קישור https ציבורי, או שאחת ההפניות שלו מובילה לכתובת שאינה כזו.
400bad_pagespages לא בנוי נכון, או שהוא לא בוחר אף עמוד בקובץ.
401unauthorizedאין מפתח, או מפתח שלא קיים או שבוטל. בתשובה יש get_key_url וכותרת WWW-Authenticate.
402payment_requiredבחשבון יש פחות עמודים ממה שהקריאה צריכה. שום דבר לא נקרא ושום דבר לא חויב.
404not_foundאין נקודת קצה כזו תחת ⁦/api/v1⁩.
405method_not_allowedשיטת HTTP לא נכונה: read ב-POST, ו-balance ב-GET.
413too_largeגוף הבקשה גדול מ-28MB, או שהקובץ גדול מ-20MB.
415unsupported_typeה-Content-Type הוא לא multipart, JSON או סוג קובץ נתמך, או שהקובץ הוא לא PDF, JPEG, PNG או WebP.
422unreadable_pdfאי אפשר לפתוח, לספור או לפצל את ה-PDF, או שהמבנה הפנימי שלו גדול מכדי לפתוח אותו.
422too_many_pagesב-PDF יש יותר מ-5000 עמודים.
422fetch_failedאי אפשר להוריד את file_url: סטטוס שגיאה, יותר מ-3 הפניות, או יותר מ-20 שניות.
429rate_limitedיותר מדי קריאות בדקה האחרונה.
500server_errorתקלה לא צפויה לפני שהקריאה התחילה. שום דבר לא חויב.
503engine_unavailableהקריאה לא זמינה כרגע. שום דבר לא חויב.

עמוד שנכשל

קריאה יכולה להצליח גם כשחלק מהעמודים שלה לא. לכל רשומה ב-⁦pages[]⁩ יש status, ולעמוד שנכשל יש גם קוד error:

status / errorמשמעות
doneהעמוד נקרא וחויב.
failedהעמוד לא נקרא והוחזר לחשבון (⁦refunded: true⁩). ה-error אומר למה:
engine_busyהקריאה הייתה עמוסה. נסו את העמוד שוב בעוד דקה.
engine_refusedאי אפשר לקרוא את העמוד הזה.
engine_failedהקריאה נכשלה. נסו שוב.
unreadable_pageאי אפשר היה להוציא את העמוד מה-PDF.
page_too_largeהעמוד גדול מ-8MB אחרי שהוצא מה-PDF.
no_pagesהעמודים בחשבון נגמרו באמצע הקריאה: העמוד הזה לא נקרא ולא חויב, ובתשובה יש buy_url.

שגיאות MCP

⁦/mcp⁩ עונה 200 עם תשובת JSON-RPC, או אצווה של תשובות, ו-202 בלי גוף כשנשלחו רק התראות או תשובות. השגיאות שלו:

HTTPJSON-RPCמתי
400-32700הגוף הוא לא JSON.
400-32600האצווה ריקה.
400-32000כותרת MCP-Protocol-Version מציינת גרסה שהשרת לא תומך בה.
403-32000ה-Origin של הבקשה נדחה.
405-32000לא POST.
413-32000הגוף גדול מ-28MB.
500-32603תקלה פנימית לפני שקריאה כלשהי התחילה. שום דבר לא חויב.
200-32600הודעה שאינה בקשת JSON-RPC: לא אובייקט, jsonrpc שאינו ⁦"2.0"⁩, method שאינו מחרוזת, או id שאינו מחרוזת או מספר שלם.
200-32601המתודה לא קיימת.
200-32602params אינו אובייקט, או שהכלי לא קיים.
200-32603תקלה פנימית בזמן קריאה. כל העמודים של הקריאה הוחזרו לחשבון.

בתוך tools/call, בעיות שמודל יכול לטפל בהן חוזרות כתוצאות כלי עם ⁦isError: true⁩, והקוד שלהן ב-⁦structuredContent.error⁩: ⁦missing_key⁩ ו-⁦invalid_key⁩ (עם get_key_url), ⁦rate_limited⁩, ו-⁦bad_request⁩ לארגומנט שהכלי לא מקבל. read_document מוסיף את הקודים של קריאת ה-REST: ⁦payment_required⁩ עם שדות התשלום, ו-⁦missing_file, bad_base64, bad_url, bad_pages, too_large, unsupported_type, unreadable_pdf, too_many_pages, fetch_failed, engine_unavailable⁩.

התיעוד הזה כ-Markdown, להקשר של מודל: /docs.md

מוכנים לנסות?

100 עמודים חינם עם המפתח הראשון. בלי כרטיס אשראי.

לקבלת מפתח API