FlyDOCТарифыКабинет

Для разработчиков

API FlyDOC

Выставляйте счета на оплату и выпускайте закрывающие документы — УПД, акты, счета-фактуры, ТОРГ-12 — прямо из своего сервиса. Номер ставим мы, документ появляется в кабинете владельца, об оплате мы сообщаем сами.

Основание всех адресов: https://api.fly-doc.ru/flydoc. Доступ входит в тариф Business.

Быстрый старт

  1. Выпустите ключ: Кабинет → Интеграции → Свои сервисы → Подключить сервис. Ключ показывается один раз — у нас остаётся только отпечаток.
  2. Выставьте счёт:
    curl -X POST https://api.fly-doc.ru/flydoc/v1/invoices \
      -H "X-Api-Key: fdk_…" \
      -H "Idempotency-Key: order-1001" \
      -H "Content-Type: application/json" \
      -d '{
        "external_reference": "shop:order:1001",
        "buyer": { "inn": "7707083893", "full_name": "ООО «Пример»" },
        "items": [{ "description": "Подписка на месяц", "quantity": 1,
                    "unit_price_kopecks": 149000, "amount_kopecks": 149000, "vat": "none" }],
        "total_kopecks": 149000
      }'
  3. Заберите PDF по id документа из ответа: GET /v1/documents/{id}/file. Когда придут деньги — мы пришлём событие invoice.payment_changed.

Доступ

Ключ передаётся заголовком:

X-Api-Key: fdk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Методы

GET/v1/accountпроверить ключ: продавец, расчётные счета
POST/v1/parties/lookupреквизиты по ИНН
POST/v1/invoicesвыставить счёт
GET/v1/invoices?external_reference=…найти свой счёт после таймаута
GET/v1/invoices/{id}счёт, суммы, состояние оплаты
GET/v1/invoices/{id}/documentsсчёт и всё, что из него выпущено
POST/v1/invoices/{id}/documentsвыпустить УПД, акт, счёт-фактуру или ТОРГ-12
POST/v1/invoices/{id}/cancelотменить неоплаченный счёт
GET/v1/documents/{id}/filePDF документа

GET/v1/account

Проверка ключа. Показывает, от чьего имени будут выставляться документы.

{
  "service": "Мой магазин",
  "seller": { "id": "7", "inn": "7707083893", "kpp": "770701001", "name": "ООО «Пример»",
              "ogrn": "1027700132195", "legal_address": "Москва", "vat": "vat" },
  "bank_accounts": [{ "id": "main", "name": "Основной", "bik": "044525225", "account": "40702810…" }],
  "default_bank_account_id": null,
  "document_types": ["INVOICE", "ACT", "UPD", "INVOICE_FACTURE", "TORG12"]
}

Продавцу без НДС счёт-фактура в document_types не предлагается.

POST/v1/parties/lookup

Название, адрес, КПП и ОГРН по ИНН из государственного справочника.

→ { "inn": "7707083893" }

← { "candidates": [{ "type": "LEGAL", "inn": "7707083893", "kpp": "773601001",
      "ogrn": "1027700132195", "full_name": "ПАО СБЕРБАНК", "short_name": "ПАО СБЕРБАНК",
      "legal_address": "г Москва, ул Вавилова, д 19", "registry_status": "ACTIVE" }] }

Пустой список — «не найдено», а не сбой. Справочник платный, поэтому у каждого ключа свой месячный предел; при превышении — 429 с Retry-After.

POST/v1/invoices

Выставить счёт. Номер ставит FlyDOC: нумерация организации обязана быть непрерывной.

{
  "external_reference": "shop:order:1001",
  "buyer": { "inn": "7707083893", "kpp": "770701001", "full_name": "ООО «Пример»",
             "legal_address": "Москва", "email": "billing@example.com" },
  "items": [{ "description": "Подписка на месяц", "quantity": 1, "unit": "усл",
              "unit_price_kopecks": 149000, "amount_kopecks": 149000, "vat": "none" }],
  "total_kopecks": 149000,
  "due_date": "2026-10-10"
}
  • Суммы — целыми копейками: 1490 ₽ это 149000. Валюта только RUB.
  • Итог сверяется со строками, а не считается нами; расхождение больше копейки — AMOUNT_MISMATCH.
  • ИНН проверяется контрольными цифрами. КПП у предпринимателя не бывает.
  • vat: none, 0, 5, 7, 10, 22. «Без НДС» и ставка 0 — разные документы. Цена указывается с НДС внутри.
  • external_reference уникален у продавца навсегда: повтор с той же ссылкой вернёт прежний счёт.

Ответ 201:

{
  "id": "inv_123", "number": "3009-01", "external_reference": "shop:order:1001",
  "status": "ISSUED", "payment_status": "UNPAID", "currency": "RUB",
  "total_kopecks": 149000, "paid_kopecks": 0, "refunded_kopecks": 0,
  "due_date": "2026-10-10", "version": 1,
  "documents": [{ "id": "doc_123", "type": "INVOICE", "number": "3009-01", "status": "ISSUED",
                  "issued_at": "2026-09-30", "file_status": "READY", "version": 1 }],
  "created_at": "2026-09-30T09:00:00.000Z"
}

Повторы. Тот же Idempotency-Key с тем же телом вернёт первоначальный ответ; с другим телом — 409 IDEMPOTENCY_CONFLICT. Память о ключе живёт сутки. После таймаута надёжнее всего сначала поискать счёт по external_reference.

GET/v1/invoices?external_reference=…

Найти свой счёт по своей ссылке — например, если ответ на создание потерялся.

← { "items": [ …счёт в том же виде, что при создании… ] }

GET/v1/invoices/{id}

Счёт с суммами и состоянием оплаты, в том же виде, что при создании.

GET/v1/invoices/{id}/documents

Счёт и всё, что из него выпущено: акты, УПД, накладные — кем бы они ни были выпущены.

{ "items": [
  { "id": "doc_123", "type": "INVOICE", "number": "3009-01", … },
  { "id": "doc_124", "type": "UPD", "number": "3009-02", … }
] }

Типы: INVOICE, ACT, UPD, INVOICE_FACTURE, TORG12.

POST/v1/invoices/{id}/documents

Выпустить закрывающий документ из счёта. Строки, суммы и стороны берутся из счёта — присылать нужно только тип и то, чего в счёте нет.

{
  "type": "UPD",
  "date": "2026-09-30",
  "fields": { "extra.basis": "Договор № 5 от 01.09.2026" },
  "allow_duplicate": false
}
  • type: UPD, ACT, INVOICE_FACTURE, TORG12. date необязательна — по умолчанию сегодня по Москве.
  • Повтор не создаёт второго документа: если документ этого типа по счёту уже есть, придёт он же с кодом 200. Вторая отгрузка — строго "allow_duplicate": true; её повтор узнаётся по Idempotency-Key.
  • УПД и счёт-фактура с пустой обязательной графой не выпускаются. Вместо документа — 422 MISSING_FIELDS со списком граф; пришлите их в fields теми же именами. Основание передачи удобнее задать один раз в правилах документов.
  • Счёт-фактура продавцу без НДС не выписывается (422 VAT_NOT_APPLICABLE), по отменённому счёту закрывающий не выпускается (409 INVOICE_CANCELED).
  • Оплата не требуется: выпускать ли документ до поступления денег, решает ваш сервис.

Ответ 201 — документ в том же виде, что в списке документов счёта, плюс invoice_id. Нехватка граф:

422
{ "error": {
    "code": "MISSING_FIELDS",
    "message": "Не хватает обязательных граф: Основание передачи",
    "fields": ["extra.basis"],
    "details": [{ "field": "extra.basis", "label": "Основание передачи", "code": "10",
                  "hint": "Договор, доверенность или иное основание" }] } }

Ответ 500 значит, что документ мог остаться под своим номером: запись создаётся раньше PDF. Прежде чем повторять, посмотрите список документов счёта.

POST/v1/invoices/{id}/cancel

Отменить неоплаченный счёт. Если по счёту есть поступления — 409 ALREADY_PAID. Отмена не означает возврата денег: поздняя оплата отменённого счёта сохраняется и видна.

GET/v1/documents/{id}/file

PDF документа — счёта или любого закрывающего.

Состояния счёта

Их два, и они независимы: поздняя оплата отменённого счёта — обычное дело.

Поступление подтверждает человек по выписке в кабинете FlyDOC. Подтверждается вся полученная сумма, а не прибавка, поэтому version растёт только при действительной перемене сумм.

Правила документов

У каждого ключа в кабинете есть правила документов: они задаются один раз и действуют на все документы по счетам этого сервиса — выпустит ли их сервис, модель или человек в кабинете.

События об оплате

Адрес событий задаётся у ключа в кабинете: Интеграции → Свои сервисы → Настроить события. Только https. Секрет рождается там же и показывается один раз.

POST <ваш адрес>
Content-Type: application/json
X-Flydoc-Timestamp: 1757251200
X-Flydoc-Signature: v1=<hex>
X-Flydoc-Event-Id: evt_…

{ "event_id": "evt_…", "type": "invoice.payment_changed", "occurred_at": "2026-09-30T09:00:00.000Z",
  "seller_id": "7707083893",
  "data": { "invoice_id": "inv_123", "external_reference": "shop:order:1001", "version": 2,
            "status": "ISSUED", "payment_status": "PAID", "currency": "RUB",
            "total_kopecks": 149000, "paid_kopecks": 149000, "refunded_kopecks": 0,
            "paid_at": "2026-09-30T09:00:00.000Z", "confirmation_source": "MANUAL" } }

Подпись — HMAC-SHA256 от строки "<timestamp>.<сырое тело>" секретом ключа. Подписывается сырое тело, а не пересобранный объект. Допустимое расхождение часов — 5 минут.

Эталон — если ваша проверка даёт то же значение, вы считаете то же, что и мы:

секрет:   whsec_0123456789abcdef0123456789abcdef0123456789abcdef
время:    1757251200
тело:     {"event_id":"evt_test","type":"invoice.payment_changed","occurred_at":"2026-09-07T12:00:00.000Z","seller_id":"7707083893","data":{"invoice_id":"inv_1","paid_kopecks":149000}}
подпись:  3827e49baf81da7d781efb3d9d33e3d567c4cb7ef4dd29df616f48cf5d13f004

Повторы. Первая попытка сразу, затем через 30 секунд, 2 минуты, 10 минут, 30 минут, 2 часа, 6 часов, 12 часов и сутки. Повторяем сетевые сбои, 429 и 5xx; 4xx — нет. У повтора та же event_id и occurred_at — по ним узнаётся дубликат. В кабинете есть журнал доставок, оттуда событие можно послать заново.

Ошибки

{ "error": { "code": "INVALID_INN", "message": "…", "fields": ["buyer.inn"] },
  "request_id": "req_…" }
UNAUTHORIZEDключ не принят: нет, неверный или отозван
PLAN_REQUIREDтариф Business не подключён или закончился
SELLER_NOT_FOUNDорганизация ключа удалена
NOT_FOUNDсчёт или документ не найден у организации ключа
INVALID_REQUESTне хватает поля или оно не в том виде
INVALID_INNИНН не проходит проверку контрольными цифрами
INVALID_KPPКПП не девять цифр или указан у предпринимателя
INVALID_AMOUNTсумма или количество не целые либо не больше нуля
INVALID_VATнеизвестная ставка НДС
AMOUNT_MISMATCHстроки не сходятся с итогом
UNSUPPORTED_CURRENCYвалюта не RUB
IDEMPOTENCY_CONFLICTIdempotency-Key уже использован с другим телом
ALREADY_PAIDпо счёту есть поступления — отменить нельзя
MISSING_FIELDSдля УПД или счёта-фактуры не хватает обязательных граф
INVOICE_CANCELEDсчёт отменён — закрывающий по нему не выпускают
VAT_NOT_APPLICABLEсчёт-фактура продавцу без НДС не выписывается
RATE_LIMITEDпревышен предел обращений; смотрите Retry-After
DIRECTORY_UNAVAILABLEсправочник реквизитов недоступен
FILE_NOT_READYPDF ещё не готов
INTERNALсбой на нашей стороне

Пределы и даты

Claude и Codex

Тот же доступ открыт модели: Claude Code и Codex выставляют счета и выпускают акты прямо в разговоре. Подключение создаётся в кабинете — Интеграции → Claude и Codex, ключ подставляется в готовую строку сам.

Выпустить ключ