OpenBadges для разработчиков
Три типа JSON-документов, цепочка из трёх HTTP-запросов, рабочий код для проверки и отличия версий 2.0 и 3.0. Здесь техническая модель — без воды и без маркетинга.
С точки зрения разработчика OpenBadges — это набор JSON-LD-документов, выложенных на стороне эмитента по обычным HTTP-URL. Никакого центрального сервера, никакого SDK, который надо лицензировать — только публично описанная модель данных и три типа документов, связанных ссылками.
В версии 2.0 проверка устроена как «дочитать цепочку JSON и сверить поля». В версии 3.0 формат переоформлен под Verifiable Credentials консорциума W3C: assertion становится подписанным credential, и проверка не требует обращения к эмитенту вовсе.
Объекты модели данных
Четыре сущности, которые описывает спецификация. Их связь — это и есть «бейдж».
- Issuer / Profile
- Кто выдаёт. Объект с id (URL), name, url и контактом. Точка доверия всей цепочки — клиент смотрит, что профиль реально размещён по этому адресу.
- Achievement / BadgeClass
- Что выдаётся. Шаблон достижения: name, description, criteria, image, теги навыков и согласования (alignment). Один BadgeClass — много assertion.
- Assertion / Credential
- Факт выдачи конкретному получателю. Ссылается на BadgeClass и эмитента, содержит recipient, issuedOn, evidence и блок verification.
- Verification
- Способ проверки. 2.0 — hosted (JSON по URL) или signed (JWS). 3.0 — криптографический proof по модели VC Data Model.
Полный цикл выдачи и проверки
Что происходит на каждом шаге, и почему ничего нельзя подделать незаметно.
Эмитент описывает себя
Публикует Profile-документ по постоянному URL — например, https://issuer.example/profile.json. Это «удостоверение» организации.
Эмитент описывает достижение
Публикует BadgeClass: за что бейдж выдаётся, критерии, картинка. Ссылка на Profile внутри.
Эмитент выдаёт бейдж конкретному человеку
Создаёт Assertion (факт выдачи) с указанием BadgeClass, получателя и даты. Получает URL вида https://issuer.example/assertions/42.
Получатель показывает ссылку
Кладёт ссылку в резюме, профиль, бэкпак. Никакой пересылки бейджа — только URL.
Проверяющий читает цепочку
GET assertion → читает badge → GET BadgeClass → читает issuer → GET Profile. Три HTTP-запроса, всё. Подлинность подтверждается тем, что данные сходятся.
Три JSON-документа
Минимальные примеры всех трёх. Этого достаточно, чтобы прочитать любой реальный бейдж 2.0.
Profile — кто выдаёт
{
"@context": "https://w3id.org/openbadges/v2",
"type": "Profile",
"id": "https://issuer.example/profile.json",
"name": "Учебный центр «Пример»",
"url": "https://issuer.example",
"email": "registry@issuer.example"
}BadgeClass — что выдаётся
{
"@context": "https://w3id.org/openbadges/v2",
"type": "BadgeClass",
"id": "https://issuer.example/badges/python-basics",
"name": "Основы Python",
"description": "Освоен синтаксис Python и решены 20 учебных задач.",
"image": "https://issuer.example/badges/python-basics.png",
"criteria": "https://issuer.example/criteria/python-basics",
"issuer": "https://issuer.example/profile.json"
}Assertion — факт выдачи
{
"@context": "https://w3id.org/openbadges/v2",
"type": "Assertion",
"id": "https://issuer.example/assertions/42",
"recipient": {
"type": "email",
"hashed": true,
"salt": "abc123",
"identity": "sha256$a1b2c3d4e5f6..."
},
"badge": "https://issuer.example/badges/python-basics",
"issuedOn": "2026-03-14T10:00:00Z",
"verification": { "type": "HostedBadge" },
"evidence": "https://issuer.example/evidence/42"
}Как прочитать бейдж из кода
Полный пример: assertion → BadgeClass → Profile. Три fetch, ноль зависимостей.
// Прочитать hosted-бейдж 2.0: assertion → BadgeClass → Profile
const assertionUrl = 'https://issuer.example/assertions/42';
const assertion = await fetch(assertionUrl).then((r) => r.json());
// 1. Достаём BadgeClass — что именно подтверждается
const badgeRef = typeof assertion.badge === 'string' ? assertion.badge : assertion.badge.id;
const badge = await fetch(badgeRef).then((r) => r.json());
// 2. Достаём Profile эмитента — кто выдал
const issuerRef = typeof badge.issuer === 'string' ? badge.issuer : badge.issuer.id;
const issuer = await fetch(issuerRef).then((r) => r.json());
// Теперь видим всё: кто, что, когда, по каким критериям
console.log({
achievement: badge.name,
issuer: issuer.name,
issuedOn: assertion.issuedOn,
verification: assertion.verification?.type,
evidence: assertion.evidence,
});Версия 3.0 — Verifiable Credentials
Тот же бейдж как W3C-credential. Подпись внутри, проверка — без обращения к эмитенту.
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"
],
"id": "https://issuer.example/credentials/42",
"type": ["VerifiableCredential", "OpenBadgeCredential"],
"issuer": {
"id": "did:web:issuer.example",
"type": "Profile",
"name": "Учебный центр «Пример»"
},
"validFrom": "2026-03-14T10:00:00Z",
"credentialSubject": {
"id": "did:example:recipient",
"type": "AchievementSubject",
"achievement": {
"id": "https://issuer.example/achievements/python-basics",
"type": "Achievement",
"name": "Основы Python",
"criteria": { "narrative": "Освоен синтаксис и решены задачи." }
}
},
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-rdfc-2022",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:web:issuer.example#key-1",
"proofValue": "z58DAdFfa9SkqZMVPxAQpic..."
}
}Как устроена проверка
- Hosted (2.0) — клиент GET-ит assertion по URL и сверяет данные с публичным Profile эмитента. Подделать assertion нельзя: ссылка ведёт на сервер эмитента, и подменить ответ может только тот, кто им владеет.
- Signed (2.0) — бейдж представлен как JWS (JSON Web Signature) с подписью эмитента. Проверяется его публичным ключом, опубликованным в Profile. Сам JWS можно носить с собой — серверу эмитента он не нужен.
- Verifiable Credentials (3.0) — проверка криптографического proof по модели W3C VC. Подпись считается через ed25519/EcDSA, верификация — полностью офлайн. Это решает кейс «эмитент закрылся, а бейдж должен оставаться проверяемым».
- Revocation — отозванные бейджи помечаются: в 2.0 — через revocationList по ссылке из Profile, в 3.0 — через StatusList2021 или аналог. Перед тем как доверять бейджу, проверьте статус.
Приватность получателя
Что хешируется, а что попадает в публичный JSON.
- Идентификатор получателя обычно хеширован — указано
hashed: trueплюсsalt. Это позволяет получателю доказать владение, но защищает от утечки e-mail при публикации бейджа. - В 3.0 получатель чаще представлен как
did:example:...— децентрализованный идентификатор, не привязанный к серверу. - Поле
evidenceможет вести на публичные материалы — решает эмитент. Не публикуйте туда персональные данные без согласия.
Точки интеграции
- LMS / EdTech — выдача бейджа по завершении курса через вебхук или платформенный API. Бейдж публикуется на хосте LMS и сразу проверяем по ссылке.
- HRM / ATS — импорт подтверждённых навыков кандидата и сотрудников. Открытый стандарт позволяет принимать бейджи из любого совместимого источника.
- Бэкпаки и кошельки — экспорт/импорт по стандарту для переносимости (OpenBadges Backpack, Badgr, Credly).
- Подписи и резюме — встраивание ссылки или баджа-картинки с запечённым assertion (PNG iTXt / SVG metadata).