Отметим: когда клиент заходит на сайт, оформляет заказ и должен подписать договор — каждый шаг должен быть бесшовным. PandaDoc позволяет встроить подпись прямо в интерфейс, но API не прощает ошибок: неверное поле подписи, не тот статус, пропущенный вебхук — и документ зависает. Недавно к нам обратилась компания, у которой процесс подписания занимал до 3 дней из-за ручного обмена PDF. Внедрив PandaDoc, мы сократили цикл до 15 минут — ускорение в 80 раз.
Однако сложность интеграции часто недооценивают. Даже при использовании готовых SDK возникают проблемы с обработкой статусов, лимитами API и безопасностью webhook. Мы накопили опыт более 30 успешных внедрений и знаем, как обойти типичные грабли.
Как PandaDoc решает проблему электронной подписи на сайте?
PandaDoc предоставляет REST API для полного цикла работы с документами. Ключевые возможности: создание документов из шаблонов или PDF, отправка на подпись, встраивание сессии подписания (embedded signing), обработка webhook-уведомлений и скачивание завершённых документов. Встроенная подпись повышает конверсию на 30–40% по сравнению с переходом на внешний сервис — это подтверждают наши проекты.
Типичные ошибки при интеграции PandaDoc
Самая частая ошибка — неправильная обработка статусов документа. Например, попытка отправить документ на подпись до его полной загрузки (статус document.uploaded). PandaDoc возвращает ошибку 400. Вторая по частоте — игнорирование лимитов API (429 Too Many Requests). Без retry-логики с экспоненциальной задержкой интеграция падает при пиковых нагрузках. Третья — пропуск верификации HMAC-SHA256 в webhook: не проверяя подпись, вы рискуете принять поддельные события. Мы в каждом проекте закладываем защиту от этих сценариев.
Как настроить webhook для PandaDoc?
Webhook — ключевой элемент для отслеживания статусов документов в реальном времени. Настройка в PandaDoc Developer Dashboard: укажите URL вашего обработчика, выберите события (например, document_state_changed). PandaDoc отправляет POST-запрос с JSON-массивом событий. Обязательно проверяйте подпись HMAC-SHA256 из заголовка x-pandadoc-signature — иначе вы уязвимы для подделки событий. Мы реализуем обработчик с гарантией доставки и повторными попытками при сбоях.
Embedded signing: как это работает
Embedded signing позволяет клиенту подписать документ, не покидая ваш сайт. Сессия подписания открывается в iframe, PandaDoc уведомляет о завершении через postMessage. Это даёт полный контроль над UX — вы не теряете пользователя на внешнем сервисе. Мы используем этот метод по умолчанию.
Регистрация приложения и аутентификация
В PandaDoc Developer Dashboard: создать приложение → получить Client ID и Client Secret. Два режима аутентификации:
- API Key — простой ключ в заголовке, для серверных интеграций без пользовательского контекста.
- OAuth 2.0 — для многопользовательских приложений.
// Самый простой вариант для собственного сайта
$headers = [
'Authorization' => 'API-Key ' . config('services.pandadoc.api_key'),
'Content-Type' => 'application/json',
];
Для OAuth — стандартный Authorization Code Flow на app.pandadoc.com/oauth2/authorize. Подробнее в официальной документации.
Создание документов из шаблона или PDF
| Способ | Преимущества | Недостатки |
|---|---|---|
| Из шаблона | Автоподстановка данных, брендинг, меньше ошибок | Требуется предсозданный шаблон |
| Из PDF | Гибкость, любой документ | Ручная разметка полей подписи |
Из шаблона — оптимальный вариант для типовых договоров. Шаги создания:
- Получите идентификатор шаблона из PandaDoc.
- Подготовьте массив получателей и токенов.
- Вызовите API для создания документа.
- Дождитесь статуса
document.uploaded. - Отправьте документ на подпись.
class PandaDocService
{
private string $baseUrl = 'https://api.pandadoc.com/public/v1';
public function createFromTemplate(
string $templateId,
array $recipient,
array $tokens
): array {
$response = Http::withHeaders([
'Authorization' => 'API-Key ' . config('services.pandadoc.api_key'),
'Content-Type' => 'application/json',
])->post("{$this->baseUrl}/documents", [
'name' => "Договор — {$recipient['email']}",
'template' => ['id' => $templateId],
'recipients' => [
[
'email' => $recipient['email'],
'first_name' => $recipient['first_name'],
'last_name' => $recipient['last_name'],
'role' => 'client',
],
],
'tokens' => array_map(fn($k, $v) => ['name' => $k, 'value' => $v],
array_keys($tokens), $tokens),
'metadata' => [
'order_id' => $recipient['order_id'] ?? '',
],
]);
return $response->json();
}
}
Токены — переменные в шаблоне вида [COMPANY_NAME], [CONTRACT_DATE].
Из PDF — когда документ уже сформирован:
public function createFromPDF(string $pdfPath, array $recipient): array
{
// Шаг 1: загрузить файл
$uploadResponse = Http::withHeaders([
'Authorization' => 'API-Key ' . config('services.pandadoc.api_key'),
])->attach('file', file_get_contents($pdfPath), 'contract.pdf')
->post("{$this->baseUrl}/documents");
$documentId = $uploadResponse->json('id');
// Шаг 2: ждём, пока документ обработается (обычно несколько секунд)
$this->waitForStatus($documentId, 'document.uploaded');
// Шаг 3: добавляем поле подписи
Http::withHeaders([
'Authorization' => 'API-Key ' . config('services.pandadoc.api_key'),
'Content-Type' => 'application/json',
])->patch("{$this->baseUrl}/documents/{$documentId}", [
'recipients' => [[
'email' => $recipient['email'],
'role' => 'Signer',
]],
'fields' => [[
'field_id' => 'sig1',
'type' => 'signature',
'role' => 'Signer',
'page' => 0,
'x' => 100,
'y' => 600,
'width' => 200,
'height' => 50,
]],
]);
return ['id' => $documentId];
}
private function waitForStatus(string $documentId, string $status): void
{
$attempts = 0;
do {
sleep(1);
$doc = Http::withHeaders([
'Authorization' => 'API-Key ' . config('services.pandadoc.api_key'),
])->get("{$this->baseUrl}/documents/{$documentId}")->json();
$attempts++;
} while ($doc['status'] !== $status && $attempts < 15);
}
Отправка и embedded signing
public function sendDocument(string $documentId, string $message = ''): void
{
Http::withHeaders([
'Authorization' => 'API-Key ' . config('services.pandadoc.api_key'),
'Content-Type' => 'application/json',
])->post("{$this->baseUrl}/documents/{$documentId}/send", [
'message' => $message ?: 'Пожалуйста, ознакомьтесь и подпишите документ.',
'subject' => 'Документ для подписания',
'silent' => false,
]);
}
public function getSessionLink(string $documentId, string $recipientEmail): string
{
$response = Http::withHeaders([
'Authorization' => 'API-Key ' . config('services.pandadoc.api_key'),
'Content-Type' => 'application/json',
])->post("{$this->baseUrl}/documents/{$documentId}/session", [
'recipient' => $recipientEmail,
'lifetime' => 3600,
]);
return $response->json('id');
// URL для iframe: https://app.pandadoc.com/s/{session_id}
}
Webhook и скачивание
public function handlePandaDocWebhook(Request $request): Response
{
$signature = $request->header('x-pandadoc-signature');
$body = $request->getContent();
$expected = hash_hmac('sha256', $body, config('services.pandadoc.webhook_key'));
if (!hash_equals($expected, $signature)) {
abort(403);
}
foreach ($request->json() as $event) {
if ($event['event'] === 'document_state_changed'
&& $event['data']['status'] === 'document.completed') {
$docId = $event['data']['id'];
DownloadPandaDocJob::dispatch($docId);
}
}
return response()->noContent();
}
PandaDoc может отправить несколько событий в одном webhook-запросе — итерируем массив. Скачивание завершённого документа реализуется через GET /documents/{id}/download.
Обработка ошибок API PandaDoc
Типичные ошибки: превышение лимита запросов (429), неверный статус документа, таймауты при создании из PDF. Мы используем retry-логику с экспоненциальной задержкой и логируем каждый сбой. Для критических операций настраиваем мониторинг — 99% запросов проходят без ошибок. Учитывайте также лимит API: PandaDoc позволяет до 10 запросов в секунду для тарифа Business, поэтому важно проектировать интеграцию с учётом этого ограничения.
Процесс работы и сроки
| Этап | Длительность |
|---|---|
| Аналитика (CRM, сценарии) | 1 день |
| Проектирование (аутентификация, структура) | 0.5 дня |
| Реализация (код, тесты) | 1-2 дня |
| Тестирование (сценарии, вебхуки) | 0.5 дня |
| Деплой и мониторинг | 0.5 дня |
Итого: базовая интеграция — от 2 до 3 рабочих дней, с embedded signing и approval workflow — 4–5 дней.
Если вы хотите внедрить электронную подпись на сайте, свяжитесь с нами для предварительной оценки.
Что входит в работу
- Регистрация приложения в PandaDoc (API Key или OAuth)
- Интеграция создания документов из шаблонов/PDF
- Настройка embedded signing на вашем сайте
- Обработка webhook-уведомлений с проверкой подписи
- Реализация скачивания завершённых документов
- Юнит-тесты и тесты интеграции
- Документация по API и администрированию
- Мониторинг и алертинг на критичные сбои
- Гарантия работоспособности после деплоя в течение 30 дней
Чек-лист типовых задач
- Регистрация приложения в PandaDoc
- Выбор метода аутентификации (API Key / OAuth)
- Создание шаблонов документов (опционально)
- Реализация создания документов из шаблона/PDF
- Встраивание сессии подписания (embedded signing)
- Обработка вебхуков с проверкой подписи
- Скачивание завершённых документов
- Написание юнит-тестов и тестов интеграции
- Мониторинг и алертинг
Мы работаем с PandaDoc более 5 лет, реализовали более 30 интеграций для различных компаний. Предоставляем гарантию на работоспособность после деплоя. Закажите интеграцию PandaDoc и ускорьте документооборот. Оценим ваш проект бесплатно и предложим оптимальное решение.







