Skip to content

تشغيل عمليات الاستخراج

نظرة عامة

تقبل نقطة نهاية الاستخراج مستنداً (مشفر بـ base64)، وتمرره عبر قالب حددته، وتُرجع بيانات منظمة تطابق متغيرات القالب. استدعاء API واحد يتولى خط الأنابيب بالكامل -- الرفع ومعالجة الذكاء الاصطناعي والمخرجات المنظمة.

جميع طلبات الاستخراج تمر عبر POST /v1/extractions/run.

تحضير مستندك

قبل إرسال مستند إلى API، تحتاج إلى تشفير محتوى الملف بـ base64.

القيود:

  • الحد الأقصى لحجم جسم الطلب: 15 ميجابايت
  • أنواع MIME المدعومة:
    • application/pdf (PDF)
    • application/vnd.openxmlformats-officedocument.wordprocessingml.document (DOCX)
bash
# Base64-encode a PDF file
base64 -i invoice.pdf -o invoice_b64.txt

# Or inline (macOS / Linux)
PDF_BASE64=$(base64 -w 0 invoice.pdf)
typescript
import { readFileSync } from "fs";

const pdfBuffer = readFileSync("invoice.pdf");
const pdfBase64 = pdfBuffer.toString("base64");
python
import base64

with open("invoice.pdf", "rb") as f:
    pdf_base64 = base64.b64encode(f.read()).decode("utf-8")

WARNING

يزيد تشفير Base64 حجم الملف بنحو 33%. ملف PDF بحجم 10 ميجابايت يصبح حوالي 13.3 ميجابايت بعد التشفير، لذا حافظ على ملفاتك المصدرية أقل من ~11 ميجابايت للبقاء ضمن حد الطلب البالغ 15 ميجابايت.

إجراء الطلب

أرسل طلب POST إلى /v1/extractions/run مع جسم JSON التالي:

الحقلالنوعمطلوبالوصف
templateIdstringنعممعرّف القالب للاستخراج
fileNamestringنعماسم الملف الأصلي (مثال: "invoice.pdf")
pdfBase64stringنعممحتوى الملف المشفر بـ Base64
mimeTypestringنعمنوع MIME للملف
runIdstringلامعرّف اختياري لتجميع عدة عمليات استخراج في دفعة
bash
curl -X POST https://api.docmap.io/v1/extractions/run \
  -H "Authorization: Bearer dm_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "tmpl_abc123",
    "fileName": "invoice.pdf",
    "pdfBase64": "JVBERi0xLjQKJeLj...",
    "mimeType": "application/pdf"
  }'
typescript
const response = await fetch("https://api.docmap.io/v1/extractions/run", {
  method: "POST",
  headers: {
    Authorization: "Bearer dm_live_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    templateId: "tmpl_abc123",
    fileName: "invoice.pdf",
    pdfBase64: pdfBase64,
    mimeType: "application/pdf",
  }),
});

const { data } = await response.json();
console.log(data.extractedData);
python
import requests

response = requests.post(
    "https://api.docmap.io/v1/extractions/run",
    headers={
        "Authorization": "Bearer dm_live_your_api_key",
        "Content-Type": "application/json",
    },
    json={
        "templateId": "tmpl_abc123",
        "fileName": "invoice.pdf",
        "pdfBase64": pdf_base64,
        "mimeType": "application/pdf",
    },
)

data = response.json()["data"]
print(data["extractedData"])

فهم الاستجابة

يُرجع الاستخراج الناجح استجابة مغلفة في كائن data:

json
{
  "data": {
    "id": "ext_abc123def456",
    "userId": "user_789",
    "templateId": "tmpl_abc123",
    "templateName": "Invoice Parser",
    "fileName": "invoice.pdf",
    "status": "completed",
    "extractedData": {
      "vendor_name": "Acme Corp",
      "invoice_number": "INV-2024-001",
      "total_amount": 1250.00,
      "line_items": [
        { "description": "Widget A", "quantity": 10, "unit_price": 125.00 }
      ]
    },
    "error": null,
    "variables": [
      { "name": "vendor_name", "type": "string", "description": "Company name of the vendor" },
      { "name": "invoice_number", "type": "string", "description": "Invoice reference number" },
      { "name": "total_amount", "type": "number", "description": "Total invoice amount" },
      { "name": "line_items", "type": "array", "description": "List of line items" }
    ],
    "source": "api",
    "runId": null,
    "processingTimeMs": 3420,
    "createdAt": "2025-07-15T10:30:00.000Z"
  }
}
الحقلالوصف
idمعرّف الاستخراج الفريد (مسبوق بـ ext_)
status"processing" أثناء التشغيل (الوضع غير المتزامن)، "completed" إذا تم استخراج البيانات بنجاح، "failed" إذا واجهت المعالجة خطأ
extractedDataكائن مفاتيحه تطابق أسماء متغيرات القالب. null إذا فشل الاستخراج
errorسلسلة رسالة الخطأ إذا فشل الاستخراج. null عند النجاح
processingTimeMsالوقت الذي استغرقه الذكاء الاصطناعي لمعالجة المستند، بالمللي ثانية
source"api" عند التشغيل عبر مفتاح API، "dashboard" عند التشغيل من واجهة الويب
variablesتعريفات متغيرات القالب التي استُخدمت لهذا الاستخراج
runIdمعرّف الدفعة الذي قدمته، أو null إذا لم يُحدد
templateNameاسم القالب المستخدم القابل للقراءة البشرية
createdAtطابع زمني ISO 8601 لوقت إنشاء الاستخراج

TIP

تحقق دائماً من حقل status قبل الوصول إلى extractedData. إذا كان status هو "failed"، فإن حقل error يحتوي على وصف لما حدث خطأ.

عمليات الاستخراج الدفعية

لمعالجة عدة ملفات كدفعة منطقية، مرّر نفس runId لكل طلب استخراج. هذا لا يغير كيفية معالجة المستندات -- يُستخرج كل ملف بشكل مستقل -- لكنه يتيح لك الاستعلام عن جميع النتائج من دفعة معاً.

typescript
const runId = "batch-invoices-2025-07";
const files = ["invoice-001.pdf", "invoice-002.pdf", "invoice-003.pdf"];

// Process each file with the same runId
const results = await Promise.all(
  files.map(async (fileName) => {
    const pdfBase64 = readFileSync(fileName).toString("base64");

    const response = await fetch("https://api.docmap.io/v1/extractions/run", {
      method: "POST",
      headers: {
        Authorization: "Bearer dm_live_your_api_key",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        templateId: "tmpl_abc123",
        fileName,
        pdfBase64,
        mimeType: "application/pdf",
        runId,
      }),
    });

    return response.json();
  })
);

ثم استرجع جميع عمليات الاستخراج من الدفعة:

bash
curl "https://api.docmap.io/v1/extractions?runId=batch-invoices-2025-07" \
  -H "Authorization: Bearer dm_live_your_api_key"
typescript
const response = await fetch(
  "https://api.docmap.io/v1/extractions?runId=batch-invoices-2025-07",
  {
    headers: { Authorization: "Bearer dm_live_your_api_key" },
  }
);

const { data } = await response.json();
console.log(`Batch contains ${data.length} extractions`);
python
response = requests.get(
    "https://api.docmap.io/v1/extractions",
    params={"runId": "batch-invoices-2025-07"},
    headers={"Authorization": "Bearer dm_live_your_api_key"},
)

data = response.json()["data"]
print(f"Batch contains {len(data)} extractions")

TIP

تدعم نقطة نهاية القائمة أيضاً التصفية حسب templateId ومعامل limit (1--100، الافتراضي 50). يمكنك دمج المرشحات: ?runId=batch-001&templateId=tmpl_abc123&limit=100.

سير العمل غير المتزامن

بشكل افتراضي، طلبات الاستخراج متزامنة -- تنتظر واجهة API حتى تنتهي المعالجة. لعمليات الاستخراج الطويلة أو عندما تريد تجنب انتهاء مهلة HTTP، استخدم الوضع غير المتزامن بإضافة ?async=true إلى عنوان URL. تُرجع واجهة API فوراً بحالة "processing"، وتستعلم عن نقطة نهاية منفصلة حتى تكون النتيجة جاهزة.

نمط الإرسال + الاستعلام

typescript
import { readFileSync } from "fs";

const API_BASE = "https://api.docmap.io";
const API_KEY = process.env.DOCMAP_API_KEY!;

// 1. Submit the extraction asynchronously
const submitResponse = await fetch(`${API_BASE}/v1/extractions/run?async=true`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    templateId: "tmpl_abc123",
    fileName: "invoice.pdf",
    pdfBase64: readFileSync("invoice.pdf").toString("base64"),
    mimeType: "application/pdf",
  }),
});

const { data: submitted } = await submitResponse.json();
console.log(`Extraction ${submitted.id} submitted, status: ${submitted.status}`);

// 2. Poll until complete
async function poll(extractionId: string): Promise<any> {
  for (let i = 0; i < 30; i++) {
    const res = await fetch(`${API_BASE}/v1/extractions/${extractionId}`, {
      headers: { Authorization: `Bearer ${API_KEY}` },
    });
    const { data } = await res.json();
    if (data.status !== "processing") return data;
    await new Promise((r) => setTimeout(r, 2000));
  }
  throw new Error("Extraction timed out");
}

const result = await poll(submitted.id);
console.log(`Final status: ${result.status}`);
console.log("Extracted data:", result.extractedData);
python
import base64
import time
import requests

API_BASE = "https://api.docmap.io"
API_KEY = "dm_live_your_api_key"
headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

# 1. Submit the extraction asynchronously
with open("invoice.pdf", "rb") as f:
    pdf_base64 = base64.b64encode(f.read()).decode("utf-8")

submit_response = requests.post(
    f"{API_BASE}/v1/extractions/run?async=true",
    headers=headers,
    json={
        "templateId": "tmpl_abc123",
        "fileName": "invoice.pdf",
        "pdfBase64": pdf_base64,
        "mimeType": "application/pdf",
    },
)

submitted = submit_response.json()["data"]
print(f"Extraction {submitted['id']} submitted, status: {submitted['status']}")

# 2. Poll until complete
def poll(extraction_id: str):
    for _ in range(30):
        res = requests.get(
            f"{API_BASE}/v1/extractions/{extraction_id}",
            headers={"Authorization": f"Bearer {API_KEY}"},
        )
        data = res.json()["data"]
        if data["status"] != "processing":
            return data
        time.sleep(2)
    raise TimeoutError("Extraction timed out")

result = poll(submitted["id"])
print(f"Final status: {result['status']}")
print("Extracted data:", result["extractedData"])

متى تستخدم الوضع غير المتزامن

استخدم الوضع غير المتزامن عند معالجة مستندات كبيرة، أو عندما يكون لعميل HTTP الخاص بك مهلات قصيرة، أو عندما تريد إرسال عدة عمليات استخراج وجمع النتائج لاحقاً. لمعظم عمليات استخراج المستند الواحد، الوضع المتزامن أبسط.

مثال سير عمل كامل

إليك مثالاً كاملاً من البداية إلى النهاية بلغة TypeScript يقرأ ملف PDF من القرص ويشغّل استخراجاً ويتعامل مع النجاح والفشل:

typescript
import { readFileSync } from "fs";

const API_BASE = "https://api.docmap.io";
const API_KEY = process.env.DOCMAP_API_KEY!;

async function extractInvoice(filePath: string) {
  // 1. Read and encode the PDF
  const pdfBuffer = readFileSync(filePath);
  const pdfBase64 = pdfBuffer.toString("base64");
  const fileName = filePath.split("/").pop()!;

  console.log(`Processing ${fileName} (${(pdfBuffer.length / 1024).toFixed(0)} KB)...`);

  // 2. Run the extraction
  const response = await fetch(`${API_BASE}/v1/extractions/run`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      templateId: "tmpl_invoice_parser",
      fileName,
      pdfBase64,
      mimeType: "application/pdf",
    }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`API error ${response.status}: ${error.error.message}`);
  }

  const { data } = await response.json();

  // 3. Check the extraction result
  if (data.status === "failed") {
    console.error(`Extraction failed: ${data.error}`);
    return null;
  }

  console.log(`Extraction completed in ${data.processingTimeMs}ms`);
  console.log("Extracted data:", JSON.stringify(data.extractedData, null, 2));

  return data.extractedData;
}

// Run it
extractInvoice("./invoices/invoice-001.pdf")
  .then((result) => {
    if (result) {
      console.log(`Vendor: ${result.vendor_name}`);
      console.log(`Total: $${result.total_amount}`);
    }
  })
  .catch(console.error);

وثائق DocMap API