Khatm

واجهة Khatm Developer Sandbox API

ادمج مسار توقيع Khatm مباشرة في تطبيقك.

أنشئ الطلبات واكتشف الحقول وأكدها وأرسل التذكيرات وألغِ المسارات واسترجع المستندات المكتملة مع أدلتها.

البدء السريع

  1. أنشئ مفتاح Sandbox من تبويب API Sandbox في مساحتك. انسخ المفتاح khatm_test_… وسرّ الـ Webhook whsec_…: يظهران مرة واحدة فقط.
  2. أنشئ طلباً مع ملف PDF والموقّعين:
curl "$KHATM_BASE_URL/v1/signature-requests" \
  -H "Authorization: Bearer $KHATM_API_KEY" \
  -F "document=@contract.pdf;type=application/pdf" \
  -F 'request={
    "client_reference": "contract-123",
    "signers": [{ "reference": "customer", "name": "Alice Martin",
      "email": "alice@example.com", "order": 1 }],
    "fields": [{ "signer_reference": "customer", "type": "signature",
      "page": 1, "x": 90, "y": 610, "width": 170, "height": 55 }]
  }'
  1. فعّله عبر POST /signature-requests/{id}/activate للحصول على signing_url لكل موقِّع.
  2. تابع الحالة عبر Webhook أو GET /signature-requests/{id}، ثم نزّل PDF الموقَّع والأدلة من /artifacts/{type}.

لا تملك الإحداثيات؟ احذف fields، واستدعِ POST /signature-requests/{id}/detect-fields، ثم أكّد الاقتراحات عبر PUT /signature-requests/{id}/fields.

العودة إلى تطبيقك

أضف return_url عند الإنشاء: بعد التوقيع (أو الرفض) يعود الموقِّع تلقائياً إلى تطبيقك. يضيف Khatm المعاملات khatm_status (signed أو declined أو cancelled أو expired) وsignature_request_id وclient_reference وsigner_reference. استخدمها للعرض، ثم أكّد النتيجة عبر API أو Webhook.

خيارات مفيدة أخرى:

  • locale (fr أو en أو ar) لكل موقِّع يحدّد لغة صفحة التوقيع.
  • sequential_signing: true يفرض ترتيب الموقّعين (order).
  • GET /signature-requests يعرض طلباتك (مرشّحا status وclient_reference وتصفّح عبر cursor).
  • POST /templates ينشئ قالباً قابلاً لإعادة الاستخدام عبر API.

تغيير موقّع

عنوان خاطئ أو غادر الشخص؟ استدعِ POST /v1/signature-requests/{id}/signers/{reference}/replace مع email (وname وlocale وsend_email). قبل التفعيل يُصحَّح الموقّع ببساطة. بعد التفعيل يُلغى الرابط السابق ويحتفظ الموقّع الجديد بالمرجع والترتيب والحقول نفسها، وتعيد الاستجابة رابط signing_url الجديد. لا يمكن استبدال موقّع سبق أن وقّع أو رفض (409).

قوالب التوقيع

يحفظ القالب مواضع التوقيعات والحقول في عقد نموذجي مرة واحدة. لكل عقد جديد بالتخطيط نفسه، ترسلون ملف PDF ومعرّف القالب: لا حاجة إلى الإحداثيات.

في مساحتكم

  1. افتحوا صفحة قوالب التوقيع وأنشئوا قالبًا من ملف PDF المرجعي.
  2. اختاروا عدد الموقّعين، ثم ضعوا التوقيعات وحقول المعلومات.
  3. احفظوا، ثم انسخوا template_id من القائمة.

عبر API

أنشئوا القالب بـ POST /v1/templates (multipart: ‏document وname وfields). ثم أرسلوا كل طلب بملف PDF المراد توقيعه وtemplate_id بدلًا من fields:

{
  "client_reference": "contrat-2026-0042",
  "template_id": "7f331696-d933-46cd-aeff-1c08151c85c1",
  "signers": [{
    "reference": "signer_1", "name": "Alice Martin",
    "email": "alice@example.com", "order": 1
  }],
  "field_values": { "contract_amount": "1 200 EUR" }
}

للعلم

  • كل signer_reference في القالب (مثلًا signer_1) هو دور: يجب أن تستخدم طلباتكم مراجع الموقّعين نفسها.
  • يملأ field_values الحقول المسمّاة في القالب، مثل contract_amount أعلاه.
  • لا يُجمع بين template_id وfields في الطلب نفسه.
  • يسرد GET /v1/templates قوالبكم الجاهزة.
  • يؤرشف DELETE /v1/templates/{id} قالبًا: لا يمكن استخدامه لطلبات جديدة، ولا تتأثر الطلبات المُنشأة سابقًا.

قوالب البريد

يحدّد قالب البريد شكل الرسائل المرسلة إلى موقّعيكم: اسم المرسل والشعار والموضوع والنص. تنشئونه مرة واحدة، ثم تذكرونه في كل طلب.

في مساحتكم

  1. افتحوا صفحة قوالب البريد وانقروا على قالب بريد جديد.
  2. أدخلوا اسم المرسل والشعار والموضوع والنص. تعرض المعاينة النتيجة بالفرنسية والإنجليزية والعربية.
  3. احفظوا، ثم انسخوا المعرّف ebr_… من القائمة.

عبر API

أنشئوا القالب بـ POST /v1/email-brands (يجب أن يكون الشعار عبر HTTPS):

{
  "sender_name": "مكتب بنعلي",
  "subject": "عقدكم جاهز للتوقيع",
  "message": "يرجى توقيع عقدكم قبل يوم الجمعة.",
  "logo_url": "https://example.com/logo.png"
}

ثم مرّروا معرّفه عند إنشاء كل طلب:

{
  "client_reference": "contrat-2026-0042",
  "email_brand_id": "ebr_…",
  "signers": [ … ]
}

للعلم

  • يُطبَّق القالب على الدعوات والتذكيرات والرسائل المرسلة إلى موقّع جديد بعد الاستبدال.
  • تُرسل كل رسالة بلغة الموقّع locale: ‏fr أو en أو ar (من اليمين إلى اليسار للعربية).
  • بدون email_brand_id يرسل Khatm رسالته القياسية.
  • القالب مشترك بين جميع مفاتيح API في الحساب.
  • لا يمكن للطلبات الجديدة استخدام قالب مؤرشف.
  • لحالة استثنائية، يمكنكم إرسال كائن email مع الطلب بدلًا من email_brand_id (لا يُجمع بينهما).

الإرسال الجماعي

يرسل POST /v1/bulk-sends قالباً واحداً إلى 50 مستلماً كحد أقصى في استدعاء واحد: يصبح كل مستلم (client_reference وsigners وfield_values) طلباً يُنشأ ويُفعَّل. تُعرض النتيجة لكل سطر (active أو already_exists أو error)، ولا يوقف سطر غير صالح بقية الأسطر. إعادة إرسال الدفعة نفسها لا تُنشئ تكراراً ولا تعيد إرسال الرسائل.

التحقق من هوية الموقّع

أضف "verification": "email_otp" إلى الموقّع. قبل رؤية المستند يتلقى رمزاً من 6 أرقام عبر البريد الإلكتروني (صالح 10 دقائق، 5 محاولات). يبقى المستند والتوقيع والرفض مقفلة على الخادم حتى إدخال الرمز. يظهر التحقق في الحالة (verified_at) وفي ملف الإثبات.

دمج التوقيع في تطبيقك

حدّد embed_origin (مثلاً https://app.example.com) عند الإنشاء. عندها يعيد التفعيل embed_url لكل موقّع لتحميله داخل <iframe> على هذا المصدر فقط، ولا يمكن لأي موقع آخر عرضه. ترسل الصفحة إلى نافذتك رسائل postMessage (signing.loaded وsigning.verification_required وsigning.signed وsigning.declined، وsigning.closed مع status عندما لا يعود الرابط صالحاً) تتضمّن signatureRequestId وclientReference وsignerReference. تحقّق من event.origin وأكّد النتيجة عبر webhook أو نقطة الحالة.

حزم SDK

تتوفر عملاء Node.js وPython وPHP دون أي اعتماديات في المستودع (sdks/). تضيف Idempotency-Key تلقائياً، وتعيد محاولة الردود 429 و503، وتتحقق من الـ webhooks.

المصادقة

يرسل كل طلب المفتاح في الترويسة Authorization: Bearer khatm_test_…. تعامل معه ككلمة مرور: احفظه على الخادم، وليس في المتصفح أو في رابط أو في السجلات. يُرفض المفتاح الملغى فوراً.

استقبال الـ Webhooks

  1. حدّدوا عنوانكم: أضيفوا callback_url (HTTPS) إلى كل طلب. يرسل Khatm إليه طلب POST بصيغة JSON عند كل تغيّر في حالة الطلب أو أحد الموقّعين.
  2. احتفظوا بالسرّ: لكل مفتاح API سرّه whsec_…، ويظهر عند إنشاء المفتاح. يمكنكم عرضه مجددًا من صفحة API Sandbox (زر سر Webhook). يُستخدم للتحقق من كل حدث (انظر أدناه).
  3. أجيبوا بسرعة: أعيدوا رمز 2xx فور الاستلام، ثم عالجوا الحدث. بدون إجابة 2xx يعيد Khatm المحاولة تلقائيًا.
  4. تابعوا الإرسالات في مساحتكم، صفحة Webhooks: كل حدث مع حالته ومحتواه وزر لإعادة إرساله.

التحقق من الـ Webhooks

يوقّع Khatm القيمة webhook-id + "." + webhook-timestamp + "." + الجسم الخام بـ HMAC-SHA256 وسرّك whsec_…. قيمة الترويسة webhook-signature هي v1, متبوعة بالتوقيع بترميز base64.

  • تحقّق من البايتات الخام بمقارنة ثابتة الزمن.
  • ارفض الطوابع الزمنية القديمة.
  • أزل التكرار عبر webhook-id: التسليم «مرة واحدة على الأقل» مع إعادة المحاولة (فوراً، ثم بعد نحو دقيقة و5 و30 دقيقة وساعتين).

الأحداث: signature_request.activated وsigner.viewed (أول فتح للرابط) وsigner.completed وsigner.declined وsigner.replaced وsigner.expired، ثم signature_request.completed أو .declined أو .cancelled أو .expired. تتضمّن أحداث الموقّع الحقل data.signer (المرجع والبريد والحالة). ترتيب الوصول غير مضمون: عند الشك اقرأ GET /v1/signature-requests/{id}.

التتبّع وإعادة الإرسال: يعرض GET /v1/webhook-deliveries كل حدث مع حالته (pending أو delivered أو failed) وآخر خطأ. بعد إصلاح المستقبِل، يعيد POST /v1/webhook-deliveries/{id}/replay إرسال الحدث فوراً بالقيمة نفسها لـ webhook-id.

الحدود والاحتفاظ

  • ملف PDF حتى 8 MiB، وحتى 10 موقّعين و100 حقل لكل طلب.
  • عند تجاوز الحد: استجابة 429 مع الترويستين X-RateLimit-Limit وX-RateLimit-Remaining.
  • انقطاع مؤقت: استجابة 503 temporarily_unavailable. أعد المحاولة بفواصل متزايدة؛ إعادة طلب الإنشاء بنفس client_reference لا تنشئ نسخة مكررة أبداً.
  • يُحذف المحتوى بعد 10 أيام من الرفع: نزّل PDF الموقَّع والأدلة قبل retention_expires_at.

API v1

  • POST /v1/signature-requests اجمع ملف PDF والموقّعين والحقول في طلب واحد واربطه بمرجع العميل.
  • POST /v1/signature-requests/{id}/activate فعّل الطلب للحصول على روابط التوقيع وأدرج كل رابط في المسار المناسب.
  • URL مسار توقيع Khatm يفتح الموقّع رابطه ويراجع المستند ويكمل الحقول المخصصة له.
  • EVENT signature_request.completed يستقبل تطبيقك حدث الاكتمال ويتحقق منه قبل تحديث مساره.
  • GET /v1/signature-requests/{id}/artifacts/{type} استرجع المستند النهائي والأدلة واربطها بملف العميل.

مواصفات OpenAPI · احصل على مفتاح sandbox