Інтегруйте електронний підпис у ваш стек
Надсилайте конверти, відстежуйте підписи, отримуйте вебхуки. Простий REST API, 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"// Plain fetch, no SDK to install.
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, яка також документує цю сторінку. Усі три залишаються узгодженими з реальним API, endpoint за endpoint, замість того щоб розходитися при першому додаванні.
Колекція Postman
25 запити організовані за доменами — конверти, документи, шаблони, печатки, вебгаки — з прикладом тіла та відповіді для кожного. Вставте свій ключ у змінну apiKey колекції, потім запустіть GET /health: вона не вимагає жодної автентифікації та підтверджує, що ваша конфігурація правильна перед першим автентифікованим викликом.
Конверти
Створення, відправка, відстеження статусу, скасування. Конверт може містити кілька документів і кількох підписувачів (паралельно або послідовно).
Вебхуки
Усі події конверта та одержувача (`envelope.sent`, `recipient.signed`, `envelope.completed`…) доставляються на URL на вашу вибір — повний список на /developers/webhooks. HMAC SHA-256 для кожного пакету для перевірки походження.
Просте аутентифікування
Bearer token. Один ключ для кожного середовища (тест / прод). Можна миттєво відкликати. Ліміт 100 запитів/хв/ключ, виділення до 200, чистий 429 з заголовком Retry-After.
Доступні endpoint'и
Усі загальнодоступні маршрути: облік, документи, конверти, шаблони, вебгаки, електронні печатки, ключі API та виставлення рахунків. Усі приймають токен Bearer та повертають 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/audit-anchors/{root} | Public: metadata of an anchored audit batch, or the .ots proof file with ?format=ots (no auth) |
| POST | /api/v1/audit-anchors/verify | Public: verify an audit entry + proof against its anchored Merkle root (no auth, reveals nothing) |
| 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, скільки ролей підписувачів має шаблон, інакше створення відхиляється з кодом 400. Поле 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
Дія «Створити конверт» у наших no-code-розширеннях охоплює лише шлях за шаблоном: поле Шаблон там є обов'язковим. Для спеціального документа, який змінюється при кожному виконанні, використовуйте дію «Завантажити документ», а потім сиру дію HTTP до POST /api/v1/envelopes, передавши повернений documentIds.
Надсилання документа: два прийняті формати
POST /api/v1/documents приймає файл двома способами на вибір. Однакові перевірки застосовуються в обох випадках: дозволені типи, ліміт 50 МБ, перевірка бінарного підпису та антивірусний аналіз.
- • У форматі multipart/form-data з частиною з назвою file. Це класичний формат, який використовують curl -F та більшість бібліотек.
- • У вигляді сирого тіла: байти файлу утворюють тіло запиту, а заголовок Content-Type вказує його тип (наприклад, application/pdf). Корисно для інструментів, які передають вміст як є, без обгортання запиту — саме це робить сполучник Power Automate.
- • У сирому тілі назва файлу не має місця в тілі: вкажіть її через заголовок X-File-Name або параметр ?fileName=. Без неї документ названий за його типом.
- • Непідтримуваний тип відповідає 415, назвавши обидва прийняті формати, а тіло, оголошене як multipart, але нечитабельне, відповідає 400. Ні те, ні інше не є помилкою сервера.
# 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 вимірює 595 × 842 пункти). x та y позначають верхній лівий кут поля, width та height — його розмір.
- • pageNumber починається з 1, documentIndex починається з 0. Номер сторінки, що виходить за межи документа, не відхиляється при створенні: поле ігнорується під час підпису й ніде не з'являється — це перша річ, яку варто перевірити, коли поле відсутнє у виклику.
- • recipientEmail має відповідати одному з отримувачів того ж виклику, незалежно від регістру. Інакше створення не вдається й виводить список усіх помилкових рядків, що уникає потреби виправляти їх по одному.
- • fields та templateId взаємно виключають один одного: шаблон уже несе власне розташування. Масив fields тому використовується лише з documentIds.
- • Прийняті типи: SIGNATURE, INITIALS, DATE_SIGNED, TEXT, CHECKBOX та RADIO_GROUP. required за замовчуванням true; placeholder та dateFormat факультативні, а options враховується лише для RADIO_GROUP.
- • Конверт приймає максимум 100 полів, 20 документів та 50 отримувачів — межі вашого плану можуть бути нижчими.
# 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 вказує, з якого боку тексту розташовується поле (за замовчуванням right, інакше below, above або left), а anchorIndex вибирає входження, коли текст з'являється кілька разів.
x та y залишаються обов'язковими навіть з якорем: вони служать резервним варіантом. Невідшукуваний якір не робить створення невдалим — поле зберігає буквальну позицію, яку ви надали, без помилки чи попередження у відповіді. Вкажіть правдоподібний резервний варіант замість 0,0 та перевірте рендеринг при першому відправленні.
Аутентифікація
Кожен виклик несе ключ 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_ створюють ресурси в пісочниці, виключені з квоти й тарифікації. Отримувачу не надсилається справжній лист, якщо тільки його адреса не збігається з email облікового запису відправника — зручно для тестування всього процесу на собі.
- • Помилки: 401 недійсний ключ, 403 недостатня область, 429 перевищена межа пропускної здатності, 402 досягнута місячна квота.
Форма відповідей
Момент, про який варто знати перед написанням вашого клієнта: колекції обгорнуті в об'єкт 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 ключ
- • Виділення допускається до 200 запитів менше ніж за 10 секунд
- • Відповідь 429 із заголовком Retry-After, який вказує затримку в секундах