Отметим: когда клиент заходит на сайт, оформляет заказ и должен подписать договор — каждый шаг должен быть бесшовным. 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 и ускорьте документооборот. Оценим ваш проект бесплатно и предложим оптимальное решение.







