Security
SSRF-hardened verifier routes
Public verify endpoints block localhost and private-network fetch targets before any server-side retrieval occurs.
API Reference
No-key routes under /public/api/* handle verification and trust discovery.
Authenticated routes under /api/* manage issuance and signing.
Minimal sequence from domain readiness to public verification.
POST /public/api/issuers/verify
Check that your domain's /.well-known/openbadges-issuer.json endpoint is reachable and returns a valid issuer profile. Rate-limited — no API key required.
POST /api/issuer
POST /api/badge-class
Register your issuer profile and define the badge class — the template that describes what the credential represents. Both endpoints require an API key.
POST /api/credential-subject
POST /api/sign-badge
Create a credential subject record for the earner, then sign the badge with your Ed25519 private key. The result is a self-contained, portable JSON assertion.
GET /public/api/verify/badge/:badgeUrl(*)
Anyone can verify a badge by URL. The public verifier fetches the JSON, validates structure and signature, and checks issuer key discoverability — returning a clear trust state with no authentication required.
Public — no key required
All verification and trust-discovery operations run without authentication.
curl "https://badges.firmament.works/public/api/verify/badge/https%3A%2F%2Fbadges.firmament.works%2Fsamples%2Fdemo-openbadge-v3-signed.json"
{
"trustState": "DEMO_DOMAIN_VERIFIED_SIGNATURE",
"issuerDomain": "example.com",
"validationLabel": "DEMO",
"keyFingerprint": "sha256:...",
"verificationReason": "Signature is valid. Issuer uses the reserved example.com demo domain.",
"issuerClaimedName": "EXAMPLE.com Demo Issuer"
}
curl "https://badges.firmament.works/public/api/trust/issuer/badges.firmament.works" curl "https://badges.firmament.works/public/api/trust/events/badges.firmament.works" curl "https://badges.firmament.works/public/api/trust/issuers?status=verified"
curl -X POST "https://badges.firmament.works/public/api/issuers/verify" \
-H "Content-Type: application/json" \
-d '{"domain":"example.org"}'
Authenticated — X-API-Key required
Issuance, signing, and admin operations require a valid API key in the request header.
X-API-Key: <API_KEY>
GET /api/validate-issuer-domain POST /api/issuer POST /api/badge-class POST /api/credential-subject POST /api/sign-badge POST /api/cache-public-key GET /api/badge-files GET /api/metrics
Agent-native
Human and LLM workflows use the same contract. See llms.txt for machine-readable docs, or connect via the MCP server for tool-native operations.
Distinct additions beyond baseline issuance and verification.
Security
Public verify endpoints block localhost and private-network fetch targets before any server-side retrieval occurs.
Trust policy
Trust writes are tied to issuer metadata at /.well-known/openbadges-issuer.json with rate limits and cooldown controls.
Interfaces
Human and LLM workflows issue, verify, and inspect trust state through the same public contract with identical semantics.
All public routes. No authentication required.
/public/api/verify/badge/:badgeUrl(*)
/public/api/verify/issuer/:issuerUrl(*)
/public/api/verify/json
/public/api/issuers/verify
/public/api/trust/issuer/:domain
/public/api/trust/events/:domain
/public/api/trust/issuers?status=verified