امضای الکترونیکی را در پشته خود ادغام کنید
پاکتها را ارسال کنید، امضاها را دنبال کنید، webhooks دریافت کنید. API REST ساده، OpenAPI 3.0، نمونههای curl/Node/Python — همه چیز برای اتصال Certyneo به HRIS، CRM یا نرمافزار تجاری خود در چند ساعت.
شروع سریع
سه مرحله: یک کلید API از تنظیمات ایجاد کنید، PDF خود را به base64 رمزگذاری کنید، ارسال کنید. پاسخ شامل `signUrl` است که میتوانید مستقیماً با گیرنده به اشتراک بگذارید.
# 1. Upload the PDF (multipart) and capture the returned document id.
DOC_ID=$(curl -s -X POST https://certyneo.com/api/v1/documents \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@contrat.pdf" | jq -r .id)
# 2. Create a DRAFT envelope referencing the uploaded document.
ENV_ID=$(curl -s -X POST https://certyneo.com/api/v1/envelopes \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d "{
\"subject\": \"Contrat de prestation\",
\"documentIds\": [\"$DOC_ID\"],
\"recipients\": [
{ \"email\": \"client@example.com\", \"name\": \"Marie Dubois\", \"role\": \"SIGNER\" }
]
}" | jq -r .id)
# 3. Dispatch the envelope — this sends the invitation email/SMS.
curl -X POST https://certyneo.com/api/v1/envelopes/$ENV_ID/send \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"// npm install @certyneo/sdk (or call fetch directly)
const auth = { Authorization: `Bearer ${process.env.CERTYNEO_API_KEY}` };
// 1. Upload the PDF (multipart).
const fd = new FormData();
fd.append("file", new Blob([pdfBuffer], { type: "application/pdf" }), "contrat.pdf");
const doc = await fetch("https://certyneo.com/api/v1/documents", {
method: "POST", headers: auth, body: fd,
}).then((r) => r.json());
// 2. Create the DRAFT envelope.
const envelope = await fetch("https://certyneo.com/api/v1/envelopes", {
method: "POST",
headers: { ...auth, "Content-Type": "application/json" },
body: JSON.stringify({
subject: "Contrat de prestation",
documentIds: [doc.id],
recipients: [
{ email: "client@example.com", name: "Marie Dubois", role: "SIGNER" },
],
}),
}).then((r) => r.json());
// 3. Dispatch — this triggers the invitation channel for every recipient.
await fetch(`https://certyneo.com/api/v1/envelopes/${envelope.id}/send`, {
method: "POST", headers: auth,
});
console.log(envelope.id);import os, requests
auth = {"Authorization": f"Bearer {os.environ['CERTYNEO_API_KEY']}"}
# 1. Upload the PDF (multipart).
with open("contrat.pdf", "rb") as f:
doc = requests.post(
"https://certyneo.com/api/v1/documents",
headers=auth,
files={"file": ("contrat.pdf", f, "application/pdf")},
).json()
# 2. Create the DRAFT envelope.
envelope = requests.post(
"https://certyneo.com/api/v1/envelopes",
headers={**auth, "Content-Type": "application/json"},
json={
"subject": "Contrat de prestation",
"documentIds": [doc["id"]],
"recipients": [
{"email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER"},
],
},
).json()
# 3. Dispatch — this triggers the invitation channel for every recipient.
requests.post(
f"https://certyneo.com/api/v1/envelopes/{envelope['id']}/send",
headers=auth,
)
print(envelope["id"])تست API از ابزارهای شما
مجموعه Postman و فیش RapidAPI از مشخصات OpenAPI تولید میشوند که این صفحه را نیز مستند میکنند. هر سه بنابراین در هر endpoint با API واقعی همراستا میمانند، نه اینکه در اولین اضافهکردن جدا شوند.
مجموعه Postman
۲۲ درخواست دستهبندیشده بر اساس دامنه — پوشهای اطلاعات، اسناد، الگوها، مهرها، webhooks — با نمونه متن و پاسخ برای هر کدام. کلید خود را در متغیر apiKey مجموعه قرار دهید، سپس GET /health را اجرا کنید: هیچ احراز هویتی نمیطلبد و تأیید میکند که پیکربندی شما قبل از اولین فراخوانی احرازشده خوب است.
پاکتها
ایجاد، ارسال، پیگیری وضعیت، لغو. یک پاکت میتواند شامل چندین سند و چندین امضاکننده (موازی یا متوالی) باشد.
Webhooks
تمام رویدادهای پاکت و گیرنده (`envelope.sent`، `recipient.signed`، `envelope.completed`…) ارسال شده به URL انتخاب شده شما — فهرست کامل در /developers/webhooks. امضای HMAC SHA-256 روی هر بار برای تأیید منشأ.
احراز هویت ساده
Bearer token. یک کلید در هر محیط (test / prod). فوری قابل لغو. حد 100 درخواست/دقیقه/کلید، burst تا 200، 429 تمیز با سرصحافه Retry-After.
نقاط انتهایی موجود
12 مسیر پوشش دهنده چرخه کامل: پاکتها، اسناد، webhooks، کلیدهای API. تمام مسیرها یک Bearer token را میپذیرند و JSON را برمیگردانند.
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/account/me | Identity of the authenticated caller (id, email, plan) — scope-less credential probe |
| POST | /api/v1/documents | Upload a PDF (multipart) — returns document id |
| GET | /api/v1/documents | List documents |
| GET | /api/v1/documents/{id} | Fetch document metadata |
| DELETE | /api/v1/documents/{id} | Delete document |
| GET | /api/v1/envelopes | List envelopes (filter with ?status= and ?limit=) |
| POST | /api/v1/envelopes | Create envelope (status: DRAFT) — from a templateId, or from documentIds with an optional fields array |
| GET | /api/v1/envelopes/{id} | Fetch envelope state |
| PATCH | /api/v1/envelopes/{id} | Update DRAFT envelope |
| DELETE | /api/v1/envelopes/{id} | Void / delete DRAFT envelope |
| POST | /api/v1/envelopes/{id}/send | Dispatch DRAFT — sends invitations |
| GET | /api/v1/envelopes/{id}/audit-trail | Download eIDAS audit-trail PDF |
| GET | /api/v1/envelopes/{id}/signed-document | Download signed PDF (once COMPLETED) |
| GET | /api/v1/envelopes/bulk | List your bulk-send jobs |
| POST | /api/v1/envelopes/bulk | Bulk send: create N envelopes from one template + a CSV (Standard/Business only) |
| GET | /api/v1/envelopes/bulk/{id} | Bulk-send job progress: counts, per-row failures, created envelopes |
| GET | /api/v1/templates | List reusable envelope templates |
| POST | /api/v1/templates | Create a template (documents, roles, positioned fields) |
| POST | /api/v1/sepa-mandates | Generate a SEPA mandate PDF and its DRAFT envelope, fields already placed |
| POST | /api/v1/payroll-adapters/normalize | Normalise a payroll CSV (Silae, Sage Paie, PayFit, Lucca) into the bulk-send shape |
| POST | /api/v1/ag-copropriete | Create a condominium general-meeting envelope (resolutions + ownership shares) |
| POST | /api/v1/ag-copropriete/{envelopeId}/votes | Record a co-owner's votes on the meeting resolutions |
| POST | /api/v1/ag-copropriete/{envelopeId}/tally | Tally the meeting - per-resolution result weighted by ownership shares |
| GET | /api/v1/videos/{videoId} | Download a stored identity video - GDPR art. 15 access path |
| GET | /api/v1/webhooks | List webhooks |
| POST | /api/v1/webhooks | Register webhook — returns the signing secret once |
| GET | /api/v1/webhooks/{id} | Fetch webhook subscription |
| PATCH | /api/v1/webhooks/{id} | Update url / events / active state |
| DELETE | /api/v1/webhooks/{id} | Unregister |
| POST | /api/v1/seals | Apply a qualified electronic seal to a document |
| GET | /api/v1/seals/{id} | Fetch seal status |
| GET | /api/v1/seals/{id}/certificate | Download the seal certificate |
| GET | /api/v1/keys | List API keys |
| POST | /api/v1/keys | Create API key — the secret is shown once |
| PATCH | /api/v1/keys/{id} | Rename / revoke key |
| DELETE | /api/v1/keys/{id} | Delete key |
| GET | /api/v1/billing/usage | Current period usage and projected cost |
| GET | /api/v1/status | Service status |
| GET | /api/v1/openapi | Machine-readable OpenAPI specification |
الگوهای پاکت
یک الگو PDF، نقشها و موقعیت فیلدهای امضا را یک بار برای همیشه ثبت میکند، سپس در هر ارسال دوباره استفاده میشود: شناسهٔ آن را در templateId به جای documentIds قرار دهید، و فیلدهای موقعیتیافته بر روی پاکت ایجادشده کپی میشوند.
- • الگوها از داشبورد ایجاد میشوند (الگوها → الگوی جدید)، جایی که سند را رها میکنید و سپس فیلدها را با ماوس موقعیت میدهید — این سادهترین راه است. API همچنین اجازه میدهد آنها را از طریق POST /api/v1/templates ایجاد کنید، با ارائهٔ اسناد، نقشها و فیلدها؛ توجه داشته باشید که فیلدها در آنجا با مختصات مطلق موقعیتیافتهاند (صفحه، x، y، عرض، ارتفاع)، بنابراین باید طرحبندی PDF را بدانید.
- • در حسابی که هنوز هیچ الگو ثبت نکرده است، GET /api/v1/templates فهرستی خالی برمیگرداند. این رفتار عادی است، نه یک خرابی احراز هویت.
- • فهرست فقط الگوهایی را شامل میشود که متعلق به کاربری هستند که مالک کلید API هستند. الگویی که توسط یک همکار ایجاد شده است در آن ظاهر نمیشود، حتی در یک فضای کاری مشترک: کلید را از حسابی تولید کنید که الگو را دارا است.
- • templateId و documentIds متقابلاً منحصر به فرد هستند: یکی یا دیگری را ارسال کنید، هرگز هر دو یا هیچ یک را نه.
- • حداقل به اندازهٔ تعداد نقشهای امضاکننده الگو، گیرندگان SIGNER فراهم کنید، در غیر این صورت ایجاد در ۴۰۰ رد میشود. فیلد signerCount برگردانده شده توسط فهرست، تعداد انتظار رفته را نشان میدهد.
- • سطح امضای الگو توسط پاکت به ارث میرسد، مگر اینکه درخواست به صراحت signatureLevel را پاس کند.
# 1. Discover the templates saved on this account.
curl -s https://certyneo.com/api/v1/templates \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"
# {
# "data": [
# { "id": "cmdq7f4k80001s6y2h1xa9pl3", "name": "Contrat de prestation",
# "signerCount": 2, "documentCount": 1, "signatureLevel": "SIMPLE" }
# ],
# "pagination": { "page": 1, "pageSize": 20, "total": 1, "pages": 1 }
# }
#
# An empty "data" array means no template exists on this account yet —
# create one from the dashboard, it is not an authentication problem.
# 2. Create the envelope FROM the template: no documentIds and no field
# coordinates, both are carried by the template. Pass one SIGNER
# recipient per signer role, in the template's role order.
curl -X POST https://certyneo.com/api/v1/envelopes \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"subject": "Contrat de prestation",
"templateId": "cmdq7f4k80001s6y2h1xa9pl3",
"recipients": [
{ "email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER" },
{ "email": "legal@example.com", "name": "Paul Martin", "role": "SIGNER" }
]
}'
# 3. The envelope is DRAFT at this point — POST /envelopes/{id}/send
# dispatches it, exactly as in the quick-start above.از Power Automate یا Zapier
عملیات «ایجاد پاکت» از متصلکنندههای بدون کد ما فقط مسیر الگو را پوشش میدهد: فیلد الگو در آنجا اجباری است. برای سند موردی که در هر اجرا تغییر میکند، از عملیات «بارگذاری سند» و سپس از عملیات HTTP خام به سمت POST /api/v1/envelopes استفاده کنید و documentIds برگردانده شده را پاس کنید.
ارسال سند: دو فرم پذیرفته شده
POST /api/v1/documents فایل را به دو روش میپذیرد، به انتخاب شما. کنترلهای یکسانی در هر دو مورد اعمال میشود: انواع مجاز، سقف ۵۰ مگابایت، تأیید امضای دودویی و تحلیل آنتیویروس.
- • در multipart/form-data، با بخشی به نام file. این فرم کلاسیک است، همانطور که curl -F و اکثر کتابخانهها.
- • در متن خام: بایتهای فایل بدنه درخواست را تشکیل میدهند و سرصحافه Content-Type نوع آن را مشخص میکند (برای مثال application/pdf). از یک ابزار که محتوا را همانطور که هست منتقل میکند، بدون بستهبندی درخواست مفید است — این کاری است که Certyneo انجام میدهد.
- • در متن خام، نام فایل جایی در بدنه ندارد: آن را از طریق سرصحافه X-File-Name یا پارامتر ?fileName= مشخص کنید. بدون آن، سند از نوع آن نامگذاری میشود.
- • یک نوع پشتیبانینشده با ۴۱۵ پاسخ میدهد و دو فرم پذیرفتهشده را نام میبرد، و بدنهای که به عنوان multipart اعلام شده است اما خوانایی ندارد ۴۰۰ پاسخ میدهد. هیچ یک از اینها خطای سرور نیست.
# a. multipart/form-data — the classic shape.
curl -X POST https://certyneo.com/api/v1/documents \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@contrat.pdf;type=application/pdf"
# b. raw body — the file bytes ARE the body, typed by Content-Type.
# The filename has nowhere to live in the body, so pass it as a header
# (or ?fileName=). Without it the document is named after its type.
curl -X POST https://certyneo.com/api/v1/documents \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/pdf" \
-H "X-File-Name: contrat.pdf" \
--data-binary "@contrat.pdf"
# Both return the same 201 with the document id to pass as documentIds.جایابی فیلدهای امضا
بدون الگو، پاکتی که از documentIds ایجاد میشود، هیچ فیلد پیشموقعیتیافته ای ندارد: امضاکننده سند را بدون مکانی برای امضا دریافت میکند. آرایهٔ fields، در همان فراخوانی ایجاد منتقل شده، هر فیلد را در نقطهٔ دقیق قرار میدهد — این معادل API است که الگو یک بار برای همیشه ثبت میکند.
- • مختصات بر حسب نقاط PDF هستند، منشأ در گوشهٔ بالا سمت چپ صفحه و محور Y به سمت پایین (صفحهٔ A4 برابر است با ۵۹۵ × ۸۴۲ نقطه). x و y گوشهٔ بالا سمت چپ فیلد را مشخص میکنند، width و height اندازهٔ آن را.
- • pageNumber از ۱ شروع میشود، documentIndex از ۰ شروع میشود. شمارهٔ صفحهای فراتر از سند در ایجاد رد نمیشود: فیلد در زمان امضا نادیده گرفته میشود و جای هیچکس ظاهر نمیشود — این اولین چیزی است که باید وقتی فیلدی در فراخوانی کم شود، بررسی کنید.
- • recipientEmail باید با یکی از گیرندگان همان فراخوانی مطابقت داشته باشد، بدون تمایز بزرگ و کوچک. در غیر این صورت ایجاد با فهرست تمام ردیفهای خاطی ناموفق است، که از تصحیح آنها یکی یکی جلوگیری میکند.
- • fields و templateId متقابلاً منحصر به فرد هستند: الگو قبلاً طرحبندی خود را دارد. بنابراین آرایهٔ fields فقط با documentIds استفاده میشود.
- • انواع پذیرفتهشده: SIGNATURE، INITIALS، DATE_SIGNED، TEXT، CHECKBOX و RADIO_GROUP. required به طور پیشفرض true است؛ placeholder و dateFormat اختیاری هستند، و options فقط برای RADIO_GROUP نگهداری میشود.
- • یک پاکت حداکثر ۱۰۰ فیلد، ۲۰ سند و ۵۰ گیرنده را میپذیرد — حدود برنامهای شما ممکن است کمتر باشد.
# Ad-hoc envelope WITH pre-placed fields — no template involved.
# Coordinates are PDF points, origin TOP-LEFT of the page, +Y downwards
# (A4 = 595 x 842 pt). x / y are the field box's top-left corner.
#
# The last field is positioned by ANCHOR instead of by eye: the server
# locates "Signature du client" in the PDF and computes the spot. x / y
# stay required there — they are the fallback if the text is not found.
curl -X POST https://certyneo.com/api/v1/envelopes \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"subject": "Contrat de prestation",
"documentIds": ["cmdq7f4k80001s6y2h1xa9pl3"],
"recipients": [
{ "email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER" }
],
"fields": [
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "SIGNATURE",
"x": 90, "y": 640, "width": 180, "height": 44 },
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "DATE_SIGNED",
"x": 320, "y": 640, "width": 140, "height": 30,
"dateFormat": "DD/MM/YYYY" },
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "TEXT",
"x": 90, "y": 700, "width": 200, "height": 30,
"placeholder": "Fonction", "required": false },
{ "recipientEmail": "client@example.com", "documentIndex": 0,
"pageNumber": 2, "fieldType": "SIGNATURE",
"anchorText": "Signature du client", "anchorPlacement": "below",
"anchorIndex": 0,
"x": 90, "y": 640, "width": 180, "height": 44 }
]
}'
# The envelope is DRAFT at this point — POST /envelopes/{id}/send
# dispatches it, exactly as in the quick-start above.لنگرهای متنی: قرار دادن یک فیلد بدون دانستن مختصات
به جای مختصات، یک فیلد میتواند متنی را که در سند چاپ شده است نام ببرد: anchorText آن را در PDF پیدا میکند و سرور موقعیت را در هنگام ایجاد محاسبه میکند. این روش زمانی ترجیح داده میشود که سند در هر ارسال دوباره تولید شود — افزودن متن، تولیدکننده قرارداد — زیرا صفحهبندی تغییر میکند اما عبارت «امضای مشتری» ثابت میماند. anchorPlacement نشان میدهد که فیلد از کدام سمت متن قرار میگیرد (بهطور پیشفرض راست، در غیر این صورت زیر، بالا یا چپ) و anchorIndex هنگامی که متن چندین بار ظاهر شود، یک رخداد را انتخاب میکند.
x و y حتی با یک لنگر اجباری هستند: آنها به عنوان بازگشت عمل میکنند. یک لنگری که قابل یافتن نیست باعث شکست ایجاد نمیشود — فیلد موقعیت لغوالحال را که شما فراهم کردید حفظ میکند، بدون خطا یا هشدار در پاسخ. بنابراین یک بازگشت معقول به جای ۰٫۰ نشان دهید و نمایش را در یک ارسال اول بررسی کنید.
احراز هویت
هر درخواست کلید API را در سرصفحه Authorization حمل میکند. کلیدها از تنظیمات → کلیدهای API تولید میشوند و تنها یک بار نمایش داده میشوند.
GET /api/v1/account/me HTTP/1.1Host: certyneo.com
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
# 200 OK
{ "data": { "id": "usr_…", "email": "you@example.com", "plan": "BUSINESS", "environment": "live" } }- • قالب: sk_live_… در تولید، sk_test_… برای صندوق شن و ماسه. سرصفحه: Authorization: Bearer <کلید>.
- • دامنهها: envelopes، documents، webhooks، seals — در خواندن (:read) یا نوشتن (:write). نوشتن خواندن را شامل میشود؛ دامنه * تمام حقوق را میدهد.
- • کلیدهای sk_test_ منابع را در صندوق شن و ماسه ایجاد میکنند، بدون سهمیه و صورتحساب.
- • خطاها: ۴۰۱ کلید نامعتبر، ۴۰۳ دامنه ناکافی، ۴۲۹ محدودیت سرعت تجاوز شده، ۴۰۲ سهمیه ماهانه رسیده است.
شکل پاسخها
نکتهای که باید قبل از نوشتن کلاینت خود بدانید: مجموعهها در یک شیء data کپسوله شدهاند، در حالی که منابع واحد به صورت مسطح برگردانده میشوند. خواندن response.data.data بر روی یک منبع واحد بنابراین undefined برمیگرداند.
// GET /api/v1/envelopes
// Collections are WRAPPED in a "data" array.
{
"data": [
{ "id": "env_abc123", "subject": "Contrat", "status": "SENT" }
]
}// GET /api/v1/envelopes/{id}
// Single resources are returned FLAT — no "data" envelope.
{
"id": "env_abc123",
"subject": "Contrat",
"status": "COMPLETED",
"recipients": [ /* … */ ]
}محدودیتهای نرخ
محدودیتها کیفیت خدمات پایدار را برای تمام مشتریان تضمین میکنند. اگر بیشتر نیاز دارید، با ما تماس بگیرید.
- • 100 درخواست در دقیقه در هر کلید API
- • Burst تا 200 درخواست در کمتر از 10 ثانیه مجاز است
- • پاسخ 429 با سرصحافه Retry-After که تأخیر را در ثانیه نشان میدهد