검증과 공유
발급(issuance)이 끝나면 조금 뒤에 서명된 크리덴셜(VC-JWT) 이 만들어집니다. 이 가이드는 그 크리덴셜을 어떻게 찾고, 어떻게 검증하고, 수령자와 어떻게 나누는지를 다룹니다. 검증 로직을 직접 구현할 일은 없습니다. 판정은 Kolleges 의 공개 검증 문이 내리고, API 는 그 문을 가리키는 포인터를 줍니다.
발급과 크리덴셜은 다른 순간입니다
섹션 제목: “발급과 크리덴셜은 다른 순간입니다”POST /v2/clubs/{clubDomain}/issuances 가 200 을 돌려준 순간 발급 기록은 생겼지만, 서명된 크리덴셜은 잠시 뒤 백그라운드에서 구워집니다. 두 시각 사이에 크리덴셜을 요청하면 409 credential-pending 을 받습니다. 폴링 대신 이벤트를 기다리세요.
-
발급합니다. 응답의
results[].resourceId가 issuance id 입니다. -
issuance.credential_issued를 기다립니다.GET /v2/clubs/{clubDomain}/events피드에 이 이벤트가 오면 서명 크리덴셜이 존재합니다.subject.id가 issuance id 입니다. -
크리덴셜을 읽습니다.
GET /v2/clubs/{clubDomain}/issuances/{issuanceId}/credential이{ id, format, jwt, payload }를 돌려줍니다.jwt는 compact JWT 원문,payload는 디코드된 클레임입니다.
// GET /v2/clubs/acme/events{ "data": [ { "id": "…", "type": "issuance.credential_issued", "occurredAt": "2026-09-03T06:12:41.000Z", "subject": { "type": "issuance", "id": "1450" } }, { "id": "…", "type": "issuance.issued", "occurredAt": "2026-09-03T06:12:38.000Z", "subject": { "type": "issuance", "id": "1450" } } ], "meta": { "nextCursor": null }}발급 상세의 credential 블록
섹션 제목: “발급 상세의 credential 블록”GET /v2/clubs/{clubDomain}/issuances/{issuanceId} 의 credential 은 크리덴셜을 가리키는 포인터입니다. 아직 구워지지 않았으면 null 입니다.
| 필드 | 뜻 |
|---|---|
id |
크리덴셜 UUID. 크리덴셜 안의 id 와 같은 값 |
format |
OB3_VC_JWT |
status |
valid · expired · revoked. 취소가 만료보다 우선. 서명은 검사하지 않습니다 |
issuedAt |
크리덴셜이 만들어진 시각 |
shareUrl |
수령자에게 보낼 공유·검증 페이지 (https://{clubDomain}.kolleges.net/credentials/{id}) |
verifyUrl |
공개 검증 API. 인증 없이 JSON 판정을 돌려줍니다 |
jwtUrl |
공개 JWT 엔드포인트. 인증 없이 서명 JWT 원문(text/plain) |
목록 항목에는 achievementId 와 credentialId 가 함께 옵니다. credentialId 가 null 이면 아직 굽기 전입니다.
인증 없는 공개 검증
섹션 제목: “인증 없는 공개 검증”검증자, 지갑, LMS 처럼 파트너 키가 없는 쪽은 Open Badges 3.0 공개 표면을 바로 부릅니다. 레퍼런스는 Open Badges 3.0 · 공개 검증에 있습니다.
| 문 | 무엇을 주나 |
|---|---|
GET https://api.kolleges.net/open-badges/v3/achievements/{issuanceId}/verify |
isValid(서명 판정) · status · issuerVerified(기관 신뢰) · payload(디코드된 VC) |
GET https://api.kolleges.net/open-badges/v3/credentials/{credentialId} |
서명 JWT 원문 (text/plain) |
GET https://api.kolleges.net/open-badges/v3/issuers/{domain}/did.json |
발급기관 DID Document (공개키) |
GET https://api.kolleges.net/open-badges/v3/issuers/{domain}/status-lists/revocation |
취소 상태 목록 (Bitstring Status List) |
verify 응답의 payload.vc.credentialSubject.achievement 에 발급 시점의 취득조건 서술(criteria.narrative), 스킬(tag, alignment), 각인 설명이 그대로 들어 있습니다. 이것이 역량 데이터에서 말한 동결 기록입니다.
// GET https://api.kolleges.net/open-badges/v3/achievements/1450/verify{ "statusCode": 200, "isValid": true, "status": "valid", "issuerVerified": true, "payload": { "iss": "did:web:api.kolleges.net:open-badges:v3:issuers:acme", "vc": { "credentialSubject": { "achievement": { "achievementType": "CertificateOfCompletion", "criteria": { "narrative": "1. 12주 커리큘럼 이수\n2. 최종 프로젝트 발표 (https://acme.example/demo-day)" }, "tag": ["React", "TypeScript", "협업"] } } } }}isValid 는 크리덴셜에 대한 판정이고 issuerVerified 는 발급기관에 대한 상업적 신뢰 인증입니다. 별개 축이라 issuerVerified 가 false 여도 서명은 유효할 수 있습니다.
수령자와 나누기
섹션 제목: “수령자와 나누기”shareUrl 을 수령자에게 보내면 됩니다. 그 페이지는 인증 없이 열리고, 크리덴셜의 현재 판정을 보여 주며, 수령자가 자기 지갑이나 SNS 로 가져가는 진입점입니다. 취소된 크리덴셜은 그 페이지에서도 취소로 보입니다.
v1 (/v1) 을 쓰고 있다면
섹션 제목: “v1 (/v1) 을 쓰고 있다면”GET /v1/achievements/{id} 의 credential { id, shareUrl, verifyUrl } | null 이 같은 포인터입니다. 일괄 발급 응답의 issued[].id 로 곧바로 되읽을 수 있습니다. 서명 JWT 원문은 위의 공개 문 credentials/{credentialId} 에서 받습니다.