API для интеграций
Всё, что вы делаете на сайте, можно делать из своей CRM, магазина или скрипта: хранить шаблоны и адреса, строить конверт одним запросом, отправлять в печать пакеты до 5 000 адресов и получать событие, когда файл готов.
Лимиты
Ключей — до 10, подписок на webhook — до 10 на аккаунт. API бесплатный; текущие условия — на странице «Тарифы».
Доступ
Запросы идут на https://dev.postapi.ru/api/v1 с ключом в заголовке:
Authorization: Bearer ваш-ключ
Ключ создаётся в кабинете, раздел «API и webhooks». Он показывается один раз: хранится только отпечаток, восстановить значение нельзя. Потерян или утёк — отзовите его и создайте новый. Удобно завести отдельный ключ на каждую интеграцию, тогда отзыв одного не ломает остальные.
Данные изолированы: по ключу видны только ваши шаблоны, адреса и задания. Чужой объект отвечает так же, как несуществующий, — 404 not_found.
Все размеры в API — в миллиметрах, начало координат — левый верхний угол лицевой стороны конверта. Даты — в формате ISO 8601.
Ошибки
Успешные ответы — JSON {"data": …} (в списках ещё meta с постраничной разбивкой). Ошибка у всех методов одной формы:
{
"error": {
"code": "invalid_data",
"message": "Данные конверта содержат ошибки.",
"details": { "recipient.postal_code": "Индекс — ровно 6 цифр." }
}
}
details — поле запроса и что в нём не так; у ошибок без подробностей это пустой объект.
| Код | Статус | Когда |
|---|---|---|
unauthenticated | 401 | Нет заголовка, ключ не найден или отозван |
account_blocked | 403 | Аккаунт заблокирован |
forbidden | 403 | Нет доступа к объекту |
read_only | 403 | Попытка изменить или удалить системный шаблон |
not_found | 404 | Объект не найден или принадлежит другому аккаунту |
file_unavailable | 409 | Файл задания ещё не готов или удалён по сроку хранения |
validation_failed | 422 | Запрос не прошёл проверку: нет обязательного поля, неверный тип |
invalid_template | 422 | Шаблон содержит ошибки: зона вне конверта, неизвестный формат и т. п. |
invalid_data | 422 | Данные конверта, адреса, профиль или webhook не прошли проверку |
text_overflow | 422 | Текст не помещается в зону даже минимальным кеглем |
rate_limited | 429 | Превышен лимит запросов; заголовок Retry-After — через сколько секунд повторить |
server_error | 500 | Внутренняя ошибка; подробности наружу не отдаются |
Лимит — 120 запросов в минуту на ключ, а не на адрес. В каждом ответе есть X-RateLimit-Limit и X-RateLimit-Remaining.
Идемпотентность
Создание задания принимает заголовок Idempotency-Key — до 80 символов: латиница, цифры и - _ : .. Если сеть оборвалась и вы повторили запрос с тем же ключом, второе задание не появится: придёт первое с кодом 200 и заголовком Idempotent-Replayed: true. Хороший ключ — номер заказа или партии в вашей системе.
Форматы
GET
/api/v1/formats
Список форматов конвертов
Нужен ключ. Заголовок Authorization: Bearer pa_…
Стандартные форматы с размерами лицевой стороны и идентификатором системного шаблона. Свой размер задаётся в шаблоне (format.code = CUSTOM, стороны от 70 до 500 мм).
Пример
curl -H "Authorization: Bearer $KEY" https://dev.postapi.ru/api/v1/formatsОтвет
{
"data": [
{ "code": "DL", "name": "DL (Е65)", "width_mm": 220, "height_mm": 110, "orientation": "landscape", "system_template": "system-dl" },
{ "code": "C5", "name": "C5", "width_mm": 229, "height_mm": 162, "orientation": "landscape", "system_template": "system-c5" }
]
}Шаблоны
Шаблон описывает конверт: формат, безопасное поле и зоны — прямоугольники в миллиметрах с типом содержимого. Системные шаблоны (system-c5 и т. д.) доступны всем и только для чтения: чтобы изменить, сделайте копию через copy_from.
| Тип зоны | Что печатает |
|---|---|
address | Адресный блок: имя, строки адреса и индекс. Данные берутся из стороны с тем же ключом (sender, recipient). Перенос по словам, автоподбор кегля |
postal_code | Индекс кодовыми знаками по образцу ГОСТ Р 51506-99; поле source — чей индекс (по умолчанию получателя) |
text | Произвольный текст: из data.fields[ключ зоны] или из поля text самой зоны |
image | Ваш логотип из профиля, вписанный в зону с сохранением пропорций |
placeholder | Пунктирная рамка с подписью — место для марки или оттиска |
GET
/api/v1/templates
Список шаблонов
Нужен ключ. Заголовок Authorization: Bearer pa_…
Сначала системные (system: true), затем ваши.
Ответ
{
"data": [
{
"id": "system-c5", "name": "C5 — стандартный", "system": true,
"format": { "code": "C5", "width_mm": 229, "height_mm": 162, "orientation": "landscape" },
"definition": { "print": { "safe_margin_mm": 5 }, "styles": { "font": "PT Sans", "size": 11 }, "zones": [ … ] },
"warnings": [], "created_at": null, "updated_at": null
}
]
}
POST
/api/v1/templates
Создать шаблон
Нужен ключ. Заголовок Authorization: Bearer pa_…
Передайте copy_from или definition. Шаблон проверяется целиком, а все ошибки возвращаются сразу, с путём к полю: zones.2.x, format.code. Зона получателя (key: recipient, type: address) обязательна.
Поля запроса
| Поле | Тип | Зачем |
|---|---|---|
name |
string | Название, до 120 символов |
copy_from |
string | id шаблона для копирования, например system-c5 |
definition |
object | Шаблон целиком: format, print, styles, zones. Нужен, если нет copy_from |
Пример
curl -X POST https://dev.postapi.ru/api/v1/templates \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"name":"Письма клиентам","copy_from":"system-c5"}'Ответ
{ "data": { "id": "01m3z…", "name": "Письма клиентам", "system": false, "format": { … }, "definition": { … }, "warnings": [] } }Поля зоны:
| Поле зоны | Тип | Зачем |
|---|---|---|
key * | string | Ключ: латиница в нижнем регистре, цифры, _ (до 32 символов), уникален в шаблоне |
type * | string | address, postal_code, text, image или placeholder |
x, y, w, h * | number | Положение и размер в мм от левого верхнего угла; зона целиком внутри конверта |
caption | string | Подпись над блоком мелким серым («Кому», «От кого») или текст в рамке |
size, min_size | number | Кегль и нижний предел автоуменьшения, пт (6–72) |
align, font, color | string | left/center/right, шрифт PT Sans, цвет #RRGGBB |
bold_name | boolean | Для address: имя полужирным |
digit_height_mm | number | Для postal_code: высота цифры 6–20 мм |
GET
/api/v1/templates/{id}
Получить шаблон
Нужен ключ. Заголовок Authorization: Bearer pa_…
Возвращает один шаблон: системный или свой.
PUT
/api/v1/templates/{id}
Изменить шаблон
Нужен ключ. Заголовок Authorization: Bearer pa_…
Только свои шаблоны. Системный отвечает 403 read_only.
Поля запроса
| Поле | Тип | Зачем |
|---|---|---|
name |
string | Новое название |
definition |
object | Новый шаблон целиком (заменяет прежний) |
DELETE
/api/v1/templates/{id}
Удалить шаблон
Нужен ключ. Заголовок Authorization: Bearer pa_…
Ответ 204 без тела. Уже созданные задания не затрагиваются.
Рендер
POST
/api/v1/render
Один конверт сразу: PDF, PNG или SVG
Нужен ключ. Заголовок Authorization: Bearer pa_…
Синхронно строит один конверт и возвращает файл, а не JSON. Страница PDF равна размеру конверта с допуском 0,1 мм (или листу, если в профиле mode: sheet). Число предупреждений — например, «кегль уменьшен» — в заголовке X-Envelope-Warnings. Если в профиле загружен логотип, он встаёт в зону image с ключом logo.
Данные конверта (data):
recipient* —name,address(строки через перевод строки),postal_code— ровно 6 цифр;sender— то же, необязательно;fields— тексты для зон типаtextпо их ключам.
Поля запроса
| Поле | Тип | Зачем |
|---|---|---|
data* |
object | Данные конверта: sender, recipient, fields (см. ниже) |
template |
string | id шаблона. Вместо него можно указать format или definition |
format |
string | Код системного формата: DL, C6, C65, C5, C4, B4, E4 |
definition |
object | Шаблон целиком, без сохранения |
output |
string | pdf (по умолчанию), png или svg |
dpi |
integer | Разрешение PNG, 50–300 |
strict |
boolean | true (по умолчанию) — текст не помещается → ошибка; false — всё равно построить |
profile |
object | Профиль печати: mode (envelope|sheet), sheet (A4|A3), offset_x_mm, offset_y_mm, scale |
printer_profile_id |
string | id профиля принтера из кабинета вместо profile |
Пример
curl -X POST https://dev.postapi.ru/api/v1/render \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"format":"C5","data":{"recipient":{"name":"Иванов Иван","address":"Невский пр-т, д. 28, кв. 5\nг. Санкт-Петербург","postal_code":"191186"}}}' \
-o konvert.pdfОтвет
200 OK
Content-Type: application/pdf (или image/png, image/svg+xml)
X-Envelope-Warnings: 1 (если были предупреждения)
<тело файла>422 text_overflow — адрес не помещается даже минимальным кеглем; в details — ключ зоны. 422 invalid_data — неверный индекс или нет получателя.
Задания
Пакетная печать идёт заданием: вы отдаёте список получателей, сервис формирует файл в очереди. Статусы: draft → queued → rendering → ready → sent_to_print → printed; при сбое — failed. О готовности можно узнать опросом GET /jobs/{id} или webhook job.ready.
POST
/api/v1/jobs
Создать задание
Нужен ключ. Заголовок Authorization: Bearer pa_…
Ответ 202 и заголовок Location. Строки с ошибками не останавливают пакет: неверный индекс или слишком длинный адрес попадают в errors задания, остальные конверты формируются. Задание падает (failed), только если не получилось ни одного конверта. Передайте Idempotency-Key, чтобы повтор запроса не создал дубль.
Поля запроса
| Поле | Тип | Зачем |
|---|---|---|
template* |
string | id шаблона |
recipients |
array | До 5 000 получателей: name, address, postal_code |
file |
file | CSV или XLSX вместо recipients (multipart/form-data); колонки «ФИО», «Адрес», «Индекс» |
address_ids / label / all |
array / string / bool | Адреса из вашей адресной книги вместо recipients |
sender |
object | Отправитель для всех конвертов; иначе — адрес с отметкой is_sender из книги |
output |
string | pdf — один файл, страница на конверт (по умолчанию); zip — файл на каждый конверт |
printer_profile_id |
string | Профиль принтера из кабинета; или profile — прямо в запросе |
name |
string | Название для списка заданий |
notify |
boolean | Прислать письмо о готовности (по умолчанию false) |
Пример
curl -X POST https://dev.postapi.ru/api/v1/jobs \
-H "Authorization: Bearer $KEY" -H "Idempotency-Key: rassylka-001" \
-F template=system-dl -F output=pdf -F file=@adresa.xlsxОтвет
{
"data": {
"id": "01m3z50beht8q837f74jszh1sf",
"name": null,
"status": "queued",
"template": { "id": "system-dl", "name": "DL (Е65) — стандартный" },
"output": "pdf",
"counts": { "total": 120, "ok": 0, "failed": 0, "pages": 0 },
"error": null,
"file": { "available": false, "url": null, "size": null, "expires_at": null },
"created_at": "2026-10-03T12:00:00+03:00"
}
}
GET
/api/v1/jobs/{id}
Статус задания
Нужен ключ. Заголовок Authorization: Bearer pa_…
Когда status станет ready, в file.url появится адрес файла. Конверты, которые не попали в файл, перечислены в errors:
Ответ
{
"data": {
"id": "01m3z50beht8q837f74jszh1sf", "status": "ready",
"counts": { "total": 120, "ok": 119, "failed": 1, "pages": 119 },
"file": { "available": true, "url": "…/api/v1/jobs/01m3z…/file", "size": 1843201, "expires_at": "2026-10-10T12:00:10+03:00" },
"errors": [ { "position": 14, "recipient": "Петров П.", "message": "Индекс — ровно 6 цифр." } ]
}
}
GET
/api/v1/jobs
Список заданий
Нужен ключ. Заголовок Authorization: Bearer pa_…
Новые сверху; в ответе meta: page, per_page, total, last_page.
Поля запроса
| Поле | Тип | Зачем |
|---|---|---|
status |
string | Фильтр по статусу |
per_page |
integer | До 100, по умолчанию 20 |
page |
integer | Номер страницы |
GET
/api/v1/jobs/{id}/file
Скачать результат
Нужен ключ. Заголовок Authorization: Bearer pa_…
PDF или ZIP. Файл хранится 7 дн., затем удаляется — после этого и пока задание не готово ответ 409 file_unavailable.
Пример
curl -H "Authorization: Bearer $KEY" -o konverty.pdf https://dev.postapi.ru/api/v1/jobs/01m3z…/file
POST
/api/v1/jobs/{id}/print
Отправить на печать
Нужен ключ. Заголовок Authorization: Bearer pa_…
Для способов, которые отправляют файл (email, cups), статус становится sent_to_print. Файл больше 20 МБ по почте не уходит.
Поля запроса
| Поле | Тип | Зачем |
|---|---|---|
adapter* |
string | download — только отметка «печатаю сам»; email — отправить файл по почте (в типографию); cups — на принтер сервера, если подключён |
email |
string | Адрес получателя файла — для adapter = email |
Адреса
Адресная книга хранится в зашифрованном виде и видна только вам. Индекс всегда проверяется: ровно 6 цифр.
GET
/api/v1/addresses
Список адресов
Нужен ключ. Заголовок Authorization: Bearer pa_…
Ответ с data и meta, как у списка заданий.
Поля запроса
| Поле | Тип | Зачем |
|---|---|---|
q |
string | Поиск по имени, адресу и индексу |
label |
string | Группа |
per_page |
integer | До 100, по умолчанию 50 |
page |
integer | Номер страницы |
POST
/api/v1/addresses
Добавить адрес
Нужен ключ. Заголовок Authorization: Bearer pa_…
Поля запроса
| Поле | Тип | Зачем |
|---|---|---|
name* |
string | ФИО или организация |
address* |
string | Адрес, строки через перевод строки |
postal_code* |
string | Индекс, 6 цифр |
label |
string | Группа для отбора, до 64 символов |
is_sender |
boolean | Адрес отправителя — подставляется в задания |
Пример
curl -X POST https://dev.postapi.ru/api/v1/addresses -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"name":"Иванов Иван","address":"Невский пр-т, д. 28","postal_code":"191186","label":"клиенты"}'Ответ
{ "data": { "id": "01m3z…", "name": "Иванов Иван", "address": "Невский пр-т, д. 28", "postal_code": "191186", "label": "клиенты", "is_sender": false, "created_at": "…" } }
POST
/api/v1/addresses/validate
Проверить адрес без сохранения
Нужен ключ. Заголовок Authorization: Bearer pa_…
Возвращает нормализованный вид (лишние пробелы убраны) и ошибки по полям. Ничего не сохраняет — удобно проверять форму у себя на сайте.
Поля запроса
| Поле | Тип | Зачем |
|---|---|---|
name, address, postal_code |
string | Те же поля, что при создании |
Ответ
{ "data": { "valid": false, "normalized": { "name": "Иванов", "address": "Москва", "postal_code": "12", "label": null, "is_sender": false }, "errors": { "postal_code": "Индекс — ровно 6 цифр." } } }
GET
/api/v1/addresses/{id}
Получить адрес
Нужен ключ. Заголовок Authorization: Bearer pa_…
PUT
/api/v1/addresses/{id}
Изменить адрес
Нужен ключ. Заголовок Authorization: Bearer pa_…
Передайте только изменяемые поля.
DELETE
/api/v1/addresses/{id}
Удалить адрес
Нужен ключ. Заголовок Authorization: Bearer pa_…
Ответ 204.
Webhooks
Вместо опроса можно получать события: когда задание меняет статус, мы отправляем POST с JSON на ваш адрес. Адрес — только https на публичный сервер: адреса во внутренней сети отклоняются. Редиректы не выполняются.
События: job.queued, job.rendering, job.ready, job.sent_to_print, job.printed, job.failed. По умолчанию подписка — на job.ready и job.failed.
{
"id": "01m3z5…",
"event": "job.ready",
"created_at": "2026-10-03T12:00:10+03:00",
"data": { …то же представление задания, что в GET /jobs/{id}… }
}
Заголовки: X-PostAPI-Event, X-PostAPI-Delivery, X-PostAPI-Timestamp и X-PostAPI-Signature: sha256=<hex>. Подпись — HMAC-SHA256 от строки <timestamp>.<тело запроса> с секретом подписки. Проверяйте её и сверяйте время, чтобы отсечь повторы старых запросов:
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', $_SERVER['HTTP_X_POSTAPI_TIMESTAMP'] . '.' . $body, $secret);
$given = substr($_SERVER['HTTP_X_POSTAPI_SIGNATURE'], 7); // без «sha256=»
if (!hash_equals($expected, $given) || abs(time() - (int) $_SERVER['HTTP_X_POSTAPI_TIMESTAMP']) > 300) {
http_response_code(401); exit;
}
Ответ 2xx — доставлено. Иначе повторы через 1, 5 и 30 минут. Подписка, у которой подряд не удались 30 доставок, отключается — включите её снова в кабинете.
POST
/api/v1/webhooks
Подписаться на события
Нужен ключ. Заголовок Authorization: Bearer pa_…
Секрет подписи возвращается только в этом ответе — сохраните его.
Поля запроса
| Поле | Тип | Зачем |
|---|---|---|
url* |
string | https-адрес вашего обработчика |
events |
array | Список событий; по умолчанию job.ready и job.failed |
Пример
curl -X POST https://dev.postapi.ru/api/v1/webhooks -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"url":"https://example.ru/hooks/postapi","events":["job.ready","job.failed"]}'Ответ
{ "data": { "id": "01m3z…", "url": "https://example.ru/hooks/postapi", "events": ["job.ready", "job.failed"], "active": true, "secret": "whsec_…" } }
GET
/api/v1/webhooks
Список подписок
Нужен ключ. Заголовок Authorization: Bearer pa_…
Секрет в списке не показывается.
GET
/api/v1/webhooks/{id}
Подписка и последние доставки
Нужен ключ. Заголовок Authorization: Bearer pa_…
В recent_deliveries — статус, число попыток и код ответа вашего сервера.
POST
/api/v1/webhooks/{id}/ping
Пробное событие
Нужен ключ. Заголовок Authorization: Bearer pa_…
Отправляет событие ping — проверить обработчик и подпись. Ответ 202.
DELETE
/api/v1/webhooks/{id}
Удалить подписку
Нужен ключ. Заголовок Authorization: Bearer pa_…
Ответ 204.
Что-то не описано или не работает?
Машинное описание всех методов — в OpenAPI; его можно загрузить в Postman или Insomnia. Остальное — напишите нам.