Разработчикам
Как встроить проверку паспорта в своего агента: открытый API проверки и реестра, JSON-схема, тестовые паспорта и готовые фрагменты кода.

API
| Запрос | Что делает |
|---|---|
GET /api/v1/check?url=example.ru | Загрузить паспорт с сайта и проверить. Можно передать адрес паспорта с #фрагментом |
POST /api/v1/check | Тело — {"url": "…"}, {"passport": {…}} или сам паспорт. Без адреса проверяются схема и подпись, уровень не присваивается |
GET /api/v1/passports | Реестр: ?q= поиск по номеру, владельцу, ИНН, агенту; ?status=; ?limit= до 200; ?offset= |
GET /api/v1/passports/AP-2026-000001 | Одна запись реестра с историей статусов и итогом последней проверки |
GET /.well-known/agent-passport.schema.json | JSON-схема формата 0.1 |
Ответ проверки
ok— true, если паспорт соответствует формату;verdict— valid, invalid, inactive или fetch_error;level— K2 или K3, только при проверке по адресу;passports[]— краткие сведения о каждом паспорте в файле;checks[]— все проверки: status ok, err, warn или info, путь к полю и текст по-русски;registry— номер и статус, если паспорт есть в реестре.
{
"ok": true,
"verdict": "valid",
"verdict_text": "Паспорт соответствует формату 0.1",
"level": "K2",
"format": "0.1",
"checked_at": "2026-10-20T09:00:00Z",
"source": {
"url": "https://example.ru/.well-known/agent-passport.json",
"http_status": 200
},
"passports": [
{
"passport_id": "https://example.ru/.well-known/agent-passport.json#zakupki",
"status": "active",
"agent_name": "Агент закупок",
"operator": "ООО «Пример»",
"signed": false,
"level": "K2"
}
],
"counts": {
"ok": 8,
"err": 0,
"warn": 0,
"info": 2
},
"checks": [
{
"status": "ok",
"code": "domain",
"path": "operator.site",
"text": "Паспорт лежит на домене оператора: example.ru"
}
]
}
Проверка в своём агенте
Перед сделкой с чужим агентом возьмите адрес его паспорта из заголовка Agent-Passport и проверьте. Свой агент предъявляет паспорт так же:
Agent-Passport: https://example.ru/.well-known/agent-passport.json#zakupki
Если не хотите зависеть от нашего сервиса, проверяйте сами: схема открыта, подпись — стандартный Ed25519 над канонической формой JSON (RFC 8785). Пример на Python справа делает всё без нашего API; на PHP — через API.
Тестовые паспорта для своих тестов — на странице примеров.
# pip install requests jsonschema cryptography import base64, json, requests, jsonschema from urllib.parse import urlparse from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey SCHEMA = "https://паспорт-агента.рф/.well-known/agent-passport.schema.json" b64d = lambda s: base64.urlsafe_b64decode(s + "=" * (-len(s) % 4)) b64e = lambda b: base64.urlsafe_b64encode(b).rstrip(b"=").decode() def jcs(v): # RFC 8785 для строк, целых чисел, true/false if isinstance(v, dict): ks = sorted(v, key=lambda k: k.encode("utf-16-be")) return "{" + ",".join(json.dumps(k, ensure_ascii=False) + ":" + jcs(v[k]) for k in ks) + "}" if isinstance(v, list): return "[" + ",".join(jcs(x) for x in v) + "]" return json.dumps(v, ensure_ascii=False) def check(site): url = f"https://{site}/.well-known/agent-passport.json" p = requests.get(url, timeout=8).json() jsonschema.validate(p, requests.get(SCHEMA).json()) assert urlparse(p["operator"]["site"]).hostname == site assert p["status"] == "active" level = "K2" for s in p.get("signatures", []): kid = json.loads(b64d(s["protected"]))["kid"] key = next(k for k in p["keys"] if k["kid"] == kid) body = {k: v for k, v in p.items() if k != "signatures"} msg = (s["protected"] + "." + b64e(jcs(body).encode())).encode() Ed25519PublicKey.from_public_bytes(b64d(key["x"])).verify(b64d(s["signature"]), msg) level = "K3" return level
$r = json_decode(file_get_contents( 'https://xn----7sbbaom0ddhbmjqf.xn--p1ai/api/v1/check?url=' . urlencode('example.ru') ), true); if ($r['ok']) { echo $r['level'], ' ', $r['passports'][0]['operator']; } else { echo 'сделку не заключаем: ', $r['verdict_text']; }
Вопросы
Сколько проверок можно делать?
До 10 в минуту с одного адреса. При превышении API отвечает 429 и заголовком Retry-After. Для массовых проверок используйте схему у себя и API — только для спорных случаев.
Можно ли вызывать API из браузера?
Да, ответы разрешены для любых сайтов (CORS). Ключ не нужен.
Что значит verdict?
valid — соответствует; invalid — есть ошибки; inactive — оформлен верно, но приостановлен, отозван или просрочен; fetch_error — не удалось загрузить.
Не государственный документ. Паспорт публикует сам оператор, реестр подтверждает только соответствие формату и подпись на дату проверки.
О проекте