CleanSign API
REST-API сервиса CleanSign для проверки электронных подписей (ЭП/ЭЦП). Принимает документы и файлы подписи через multipart/form-data, возвращает JSON со сведениями о подписантах, цепочкой сертификатов и классификацией подписи. Использует тот же движок проверки, что и веб-форма на главной странице. Подходит для пакетной обработки документов и мониторинга срока действия сертификатов; готовых коннекторов к учётным системам и операторам ЭДО сервис не поставляет — встраивание выполняется на стороне клиента.
https://api.cleanvoice.ru/cleansign/api/v1.
Какие проверки выполняются
- Соответствие хеша документа подписанному атрибуту
messageDigest— отсекает подмену подписанного содержимого. - Криптографическая проверка подписи (ГОСТ Р 34.10-2012, RSA, ECDSA).
- Построение цепочки сертификатов до закреплённого trust-anchor (ГУЦ Минцифры) в режиме fail-closed.
- Проверка привязки
signingCertificateV2(RFC 5126), исключающая подмену сертификата подписанта. - Проверка аккредитации УЦ-эмитента в реестре Минцифры на текущий момент и на момент подписания.
- Опционально: проверки OCSP и CRL, верификация контр-подписей и меток времени CAdES (профили BES — A).
- Классификация подписи по 63-ФЗ — КЭП (она же УКЭП — усиленная квалифицированная), НЭП (усиленная неквалифицированная) или иная — с указанием класса средства ЭП (КС1, КС2, КС3) и СКЗИ.
Поддерживаемые форматы
- CMS / PKCS#7 — отделённая подпись в виде самостоятельного файла рядом с документом. Расширения:
.sig,.sgn,.sign,.p7s,.bin(плюс числовые суффиксы вида.sig2,.sig.001). Документом может быть любой файл —.pdf,.docx,.xlsx,.doc,.xml,.txt,.html,.rtfи любой бинарный. - CAdES — те же расширения, что и CMS; распознаются профили BES, EPES, T, C, X-L, X Long Type 1, A.
- PAdES — встроенная подпись в PDF (
.pdf): чтение/ByteRange,/Contents, поддержка нескольких подписей в одном документе и словаря/DSS(DSS dictionary). - S/MIME — почтовые сообщения
multipart/signed. Расширения:.eml,.p7m,.mime,.msg. - XMLDSig / XAdES — XML-файлы (
.xml) с алгоритмами ГОСТ или RSA; поддерживаются преобразованияc14n,exc-c14nиenveloped-signature. - OOXML —
.docx,.xlsx,.pptxс поддержкойRelationshipTransformпо ECMA-376 §13. - ZIP-архивы —
.zipраспаковывается на один уровень: документы и подписи внутри сопоставляются по содержимому (хеш) и по имени; поддержка имён в кодировке CP866. Зашитые внутрь архива другие архивы хранятся как опаковые байтовые блобы и отдельно не распаковываются. Применяются защитные лимиты: число записей, размер записи, кумулятивный размер, коэффициент сжатия (zip-bomb), глубина вложенности папок и потенциальной рекурсии (см.CleanSign:Limits).
Версионирование
Канонические пути API располагаются под префиксом /api/v{N}/. Контракт v1 зафиксирован: в существующие ответы могут добавляться новые необязательные поля, но имена и типы существующих полей не изменяются и не удаляются. Несовместимое изменение (переименование поля, изменение типа, удаление секции ответа) выпускается параллельной версией /api/v2; /api/v1 продолжает работать в прежнем виде.
Незаверсионированные пути /api/verify и /api/cert/check — это псевдонимы, ведущие на текущую актуальную версию. Они сохраняются для обратной совместимости со старыми интеграциями. В новых интеграциях используйте только версионированные пути, чтобы зафиксировать контракт.
Аутентификация
Доступ к API авторизуется по токену. Токен выдаётся при подключении и передаётся в заголовке Authorization: Bearer <token>. Запросы без валидного токена отклоняются с кодом 401 Unauthorized.
Все запросы выполняются по HTTPS. Максимальный размер тела запроса — 200 МБ.
Коды ошибок
| HTTP | Когда | Что вернётся |
|---|---|---|
| 200 OK | Запрос обработан. Невалидная подпись — это штатный результат проверки, статус по каждому файлу возвращается в items[i].status. | JSON: VerificationResponse или CertificateCheckResponse |
| 400 Bad Request | Запрос не в формате multipart/form-data, отсутствует поле с файлами или повреждена форма. | { "error": "..." } |
| 413 Payload Too Large | Превышен один из лимитов: размер запроса, размер записи в архиве, число записей, коэффициент сжатия (защита от zip-bomb). | { "error": "..." } с указанием конкретного лимита |
| 500 Internal Server Error | Внутренняя ошибка сервиса. | { "error": "..." } |
items[i].isValid и items[i].status.POST /api/v1/verify
Проверяет одну или несколько связок «документ + подпись». Принимает ZIP-архивы (распаковываются рекурсивно), пары вида «doc.pdf + doc.pdf.sig», PDF со встроенной PAdES-подписью, .eml с S/MIME, файлы .docx, .xlsx, .pptx и .xml (XMLDSig).
Параметры запроса (query или поле формы)
| Поле | Тип | Описание |
|---|---|---|
| files | file[] | Один или несколько файлов. Документ и подпись могут передаваться отдельными частями формы либо одним ZIP-архивом. Имя поля формы — files. |
| returnSignatureFile | bool | Если true, в каждый элемент результата добавляется signatureFileBase64 — байты файла подписи в base64 (для отделённой подписи), внутренний CMS (для PAdES и S/MIME) либо файл sig*.xml (для OOXML). Значение по умолчанию — false. |
| returnCertificateFile | bool | Если true, в каждом подписанте возвращается поле certificateBase64 с DER-представлением сертификата подписанта в base64. Значение по умолчанию — false. |
Пример запроса
curl -X POST 'https://api.cleanvoice.ru/cleansign/api/v1/verify?returnCertificateFile=true' \
-F 'files=@invoice.pdf' \
-F 'files=@invoice.pdf.sig' \
-H 'Authorization: Bearer YOUR_KEY'
import requests
files = [
('files', ('invoice.pdf', open('invoice.pdf', 'rb'))),
('files', ('invoice.pdf.sig', open('invoice.pdf.sig', 'rb'))),
]
resp = requests.post(
'https://api.cleanvoice.ru/cleansign/api/v1/verify',
params={'returnCertificateFile': 'true'},
files=files,
headers={'Authorization': 'Bearer YOUR_KEY'},
)
data = resp.json()
print(data['summary']['validlySigned'], 'valid of', data['summary']['totalDocuments'])
const fd = new FormData();
fd.append('files', pdfFile, 'invoice.pdf');
fd.append('files', sigFile, 'invoice.pdf.sig');
const r = await fetch('https://api.cleanvoice.ru/cleansign/api/v1/verify?returnCertificateFile=true', {
method: 'POST',
body: fd,
});
const data = await r.json();
console.log(data.summary.validlySigned + ' / ' + data.summary.totalDocuments);
using var http = new HttpClient { BaseAddress = new Uri("https://api.cleanvoice.ru/cleansign/") };
http.DefaultRequestHeaders.Authorization = new("Bearer", "YOUR_KEY");
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(File.ReadAllBytes("invoice.pdf")), "files", "invoice.pdf");
form.Add(new ByteArrayContent(File.ReadAllBytes("invoice.pdf.sig")), "files", "invoice.pdf.sig");
var resp = await http.PostAsync("api/v1/verify?returnCertificateFile=true", form);
var json = await resp.Content.ReadAsStringAsync();
Пример ответа (200 OK)
{
"summary": {
"totalDocuments": 1,
"signed": 1,
"validlySigned": 1,
"invalidSignatures": 0,
"notSigned": 0,
"orphanSignatures": 0
},
"items": [
{
"documentFile": "invoice.pdf",
"documentSize": 182734,
"signatureFile": "invoice.pdf.sig",
"isSigned": true,
"isValid": true,
"status": "Valid",
"documentHashAlgorithm": "GOST R 34.11-2012 (256)",
"documentHashHex": "8E5C…",
"messageDigestMatches": true,
"isPowerOfAttorney": false,
"signers": [
{
"subjectCommonName": "Иванов Иван Иванович",
"subjectType": "ЮЛ",
"signerShortName": "Иванов И. И.",
"signingTime": "2026-04-30T17:42:11+00:00",
"signatureValid": true,
"trustStatus": "Trusted",
"chainTrusted": true,
"trustedRootSubject": "CN=Минцифры России",
"classification": { "kind": "КЭП", "kindFull": "Квалифицированная электронная подпись",
"classes": ["КС1"], "subjectSignTool": "КриптоПро CSP (5.0.12000)",
"usesGost": true, "issuedByAccreditedUc": true, "isGoskey": false,
"deprecationWarnings": [] },
"attributes": { "inn": "772372861423", "innLe": "7709000010",
"ogrn": "1047709098315", "snils": "14233464635",
"email": "i.ivanov@example.com",
"givenName": "Иван Иванович", "surname": "Иванов",
"organization": "ООО «Пример»" },
"accreditation": { "currentStatus": "Accredited", "atSigningTimeStatus": "Accredited" },
"certificateBase64": "MIIH…" // только если returnCertificateFile=true
}
],
"errors": [],
"warnings": []
}
]
}
POST /api/v1/cert/check
Проверка только сертификата, без документа. Эндпоинт оптимизирован для регулярных запусков из cron. Принимает .cer, .crt, .pem, .der или CMS-файл (.sig); во втором случае сертификат подписанта извлекается по SignerID. Возвращает срок действия, число дней до истечения, аккредитацию УЦ, статус OCSP и CRL, классификацию.
Пример: ежедневный мониторинг
#!/bin/bash
# Завершиться с ошибкой, если до истечения сертификата осталось менее 30 дней.
RESP=$(curl -sf -F files=@/etc/ssl/edo.cer https://api.cleanvoice.ru/cleansign/api/v1/cert/check)
DAYS=$(echo "$RESP" | jq '.items[0].daysUntilExpiry')
[ "$DAYS" -lt 30 ] && echo "ALERT: cert expires in $DAYS days" && exit 1
Пример ответа
{
"summary": { "total": 1, "currentlyValid": 1, "expiringSoon": 0, "expired": 0,
"trusted": 1, "untrusted": 0, "revoked": 0 },
"items": [{
"fileName": "edo.cer",
"source": "X509",
"subjectCommonName": "ООО «Пример»",
"issuer": "CN=Удостоверяющий центр Федерального казначейства",
"notBefore": "2025-08-12T08:14:00+00:00",
"notAfter": "2026-08-12T08:14:00+00:00",
"isCurrentlyValid": true,
"daysUntilExpiry": 97,
"publicKeyAlgorithm":"GOST R 34.10-2012 (256)",
"classification": { "kind": "КЭП", "classes": ["КС1"], "issuedByAccreditedUc": true },
"trust": { "status": "Trusted", "trusted": true,
"rootSubject": "CN=Минцифры России",
"chain": [...] },
"accreditation": { "currentStatus": "Accredited" },
"revocation": null,
"revocationCrl": null
}]
}
VerificationResponse
Ответ POST /api/v1/verify.
| Поле | Тип | Описание |
|---|---|---|
| summary | object | Сводка по всему запросу. |
| summary.totalDocuments | int | Сколько документов было распознано. |
| summary.signed | int | Из них подписанных (любым статусом, включая невалидные). |
| summary.validlySigned | int | Из подписанных — прошедших полную проверку (status=Valid). |
| summary.invalidSignatures | int | Подписанных с фейлом (хэш не совпал, недоверенная цепочка, пр.). |
| summary.notSigned | int | Документов, для которых не нашлось подписи. |
| summary.orphanSignatures | int | Подписей без сопоставленного документа. |
| items | DocumentVerificationResult[] | Результат по каждому документу/паре. См. ниже. |
DocumentVerificationResult
| Поле | Тип | Описание |
|---|---|---|
| documentFile | string | Имя/путь документа (включая путь внутри архива, если это ZIP). |
| documentSize | long | Размер документа в байтах. |
| signatureFile | string? | Имя/путь файла подписи. null для NotSigned. Для встроенной подписи — синтетическое имя вроде doc.pdf (PAdES). |
| isSigned | bool | Найдена ли вообще какая-либо подпись. |
| isValid | bool | Прошла ли подпись все обязательные проверки. true ↔ status=Valid. |
| status | string | Один из: Valid, Untrusted, DocumentHashMismatch, InvalidSignature, InvalidSignatureContainer, OrphanSignature, NotSigned, UnverifiedXmlSignature. |
| documentHashAlgorithm | string? | Человекочитаемое имя алгоритма (например, «GOST R 34.11-2012 (256)»). |
| documentHashHex | string? | Hex-представление вычисленного хеша документа. |
| messageDigestMatches | bool? | Совпал ли хеш документа с подписанным атрибутом messageDigest. false = «приклеили чужую подпись». |
| isPowerOfAttorney | bool | Файл является МЧД (машиночитаемой доверенностью) — определяется по имени ON_EMCHD_*.xml. |
| signers | SignerInfoResult[] | Информация по каждому подписанту. Обычно один элемент. |
| errors | string[] | Ошибки, делающие подпись невалидной. |
| warnings | string[] | Предупреждения (deprecated алгоритмы, отсутствие OCSP-эндпойнта и т. п.). |
| signatureFileBase64 | string? | Заполняется только при returnSignatureFile=true. |
SignerInfoResult
Полная карточка подписанта. Поля сгруппированы для удобства.
Идентификация
| subjectCommonName | string | CN из Subject DN. |
| subject | string | Полный Subject DN. |
| issuer | string | Полный Issuer DN. |
| serialNumber | string | Серийный номер сертификата (hex). |
| subjectType | string? | «Физлицо» / «ИП» / «ЮЛ» / null — определяется по российским OID-ам. |
| signerShortName | string? | Компактное «Иванов И. И.» если есть фамилия и имя в attributes. |
| attributes | RussianSubjectAttributes | ИНН, ИНН ЮЛ, ОГРН, ОГРНИП, СНИЛС, email, surname, givenName, organization, organizationUnit, country, locality, title. |
Срок действия и алгоритмы
| certNotBefore | datetime | Начало срока действия сертификата (ISO-8601 UTC). |
| certNotAfter | datetime | Конец срока действия. |
| certificateTimeValid | bool | Был ли сертификат действителен в момент подписания. |
| digestAlgorithmOid | string | OID алгоритма хеширования. |
| digestAlgorithmName | string | Человекочитаемое имя. |
| signatureAlgorithmOid | string | OID алгоритма подписи. |
| signatureAlgorithmName | string | Имя. |
| signingTime | datetime? | Из подписанного атрибута signingTime (если есть). |
Криптопроверка и доверие
| signatureValid | bool | Прошла ли криптоматематика подписи. |
| signatureError | string? | Текст ошибки, если signatureValid=false. |
| trustStatus | string | Один из: Trusted, UntrustedRoot, BrokenChain, SignatureFailure, Expired, TrustStoreEmpty. |
| chainTrusted | bool | Завершилась ли цепочка на закреплённом anchor-е (ГУЦ Минцифры). |
| trustedRootSubject | string? | Subject корневого сертификата, если он в trust-store. |
| chain | CertificateChainLink[] | Цепочка leaf → ... → root. Каждый узел: subject, issuer, serialNumber, notBefore, notAfter, inTrustStore. |
| trustErrors | string[] | Подробности проблем доверия. |
Расширенная информация
| classification | SignatureClassification | kind (КЭП/НЭП/Иная), kindFull, reason, classes (КС1/КС2/КС3), subjectSignTool (СКЗИ), usesGost, issuedByAccreditedUc, isGoskey, deprecationWarnings. |
| cades | CadesProfile? | Уровень CAdES: BES, EPES, T, C, X-L, X Long Type 1, A. |
| timestamps | TimestampResult[] | Метки времени с проверенной TSA-подписью. |
| revocation | OcspResult? | OCSP-проверка (опционально, off by default). |
| revocationCrl | CrlResult? | CRL-проверка (опционально). |
| accreditation | AccreditationCheck? | Аккредитация УЦ: currentStatus + atSigningTimeStatus. |
| counterSignatures | CounterSignatureInfo[] | Контр-подписи (id-aa-counterSignature). |
| signingCertBinding | object? | Проверка signingCertificateV2 (RFC 5126): Verified / Mismatch / Malformed / NotPresent. |
| certificateBase64 | string? | DER сертификата в base64 — только при returnCertificateFile=true. |
CertificateCheckResponse
Ответ POST /api/v1/cert/check. Структура простая:
| summary.total | int | Сколько файлов прислали. |
| summary.currentlyValid | int | Действительных сейчас. |
| summary.expiringSoon | int | Истекают в ближайшие 30 дней. |
| summary.expired | int | Уже истекли. |
| summary.trusted | int | Цепочка ведёт к закреплённому anchor-у. |
| summary.untrusted | int | Цепочка не выстроилась или anchor другой. |
| summary.revoked | int | Отозваны (по OCSP или CRL, если включены). |
| items[i] | CertificateCheckResult | fileName, source, subject, issuer, serialNumber, notBefore, notAfter, isCurrentlyValid, daysUntilExpiry, publicKeyAlgorithm, signatureAlgorithm, deprecationWarnings, classification, trust, accreditation, revocation, revocationCrl, attributes. Производный признак «истекает скоро» вычисляется на стороне клиента из daysUntilExpiry по своему порогу. |
Типичные интеграции
Сценарии, в которых API применяется на практике.
Учётные системы (1С, SAP, ERP)
При приёме входящего УПД, акта или счёта-фактуры файл автоматически направляется на /api/v1/verify; проводка блокируется, если подпись контрагента невалидна или сертификат отозван.
Операторы ЭДО
Кросс-проверка пакетов от смежных операторов и ФНС: PDF + .sig, ON_DOCNPNO, KV-квитанции, confirmation.*. Автоматическое сопоставление по содержимому, единый формат отчёта.
Финтех, банки, факторинг
Перед выкупом дебиторской задолженности выполняется автоматическая проверка договора поставки: валидная КЭП обеих сторон, цепочка до ГУЦ Минцифры, аккредитация УЦ на момент подписания.
Госорганы и B2G
Приём электронных обращений: проверка подписи заявителя, классификация (КЭП, НЭП), привязка к ФЛ, ИП или ЮЛ по ИНН, СНИЛС и ОГРН, выявление машиночитаемой доверенности (МЧД).
Мониторинг сертификатов через cron
Эндпоинт /api/v1/cert/check запускается раз в сутки по сертификатам ЭДО и API-партнёров; формирует оповещение за Х дней до истечения, при отзыве сертификата или при потере аккредитации УЦ.
curl -F files=@cert.cer \
https://api.cleanvoice.ru/cleansign/api/cert/check \
| jq '.items[0].daysUntilExpiry < 30'
Долгосрочное хранение
При помещении документа в архив фиксируется уровень CAdES (от BES до A), валидируются метки времени, сохраняется цепочка сертификатов и снимок реестра аккредитации УЦ в качестве доказательственной базы.
Состав подписки
Подписка включает не только доступ к API, но и операционное обслуживание сервиса в режиме 24/7:
| Компонент | Состав |
|---|---|
| Актуальный trust-store | Автоматическое обновление: загрузка новых промежуточных сертификатов через AIA, обработка ротации ключей УЦ, актуальные точки распространения CRL. |
| Синхронизация с реестром Минцифры | Загрузка обновлений с e-trust.gosuslugi.ru: добавление новых аккредитованных УЦ, аннулирования, изменения статуса. |
| Сопровождение форматов | Адаптация движка к новым форматам (Goskey 2.x, новые OID Минцифры, изменения 63-ФЗ). Обновления применяются на стороне сервиса без действий со стороны клиента. |
| Производительность | Горизонтальное масштабирование под пиковую нагрузку. |
| SLA и поддержка | Целевая доступность 99.95%. |
| Журналы и метрики | Панель статистики статусов проверки, настраиваемое хранение, аудит. |
Запросить стоимость
В письме укажите сценарии использования и ожидаемый объём верификаций в месяц.