API documentation
All endpoints are public (no edge auth) and live under /api/public/v1. Issuance requires a Bearer API key created in the admin dashboard.
POST /api/public/v1/credentials/issue
Validates the source URL against the allow-list, scrapes it with the configured parser, maps the extracted fields onto a Hovi credential template, and returns an OpenID4VCI credential_offer deeplink the wallet can open.
Headers
Authorization: Bearer vci_xxxxxxxx Content-Type: application/json
Body
{
"source_url": "https://mdl.rtad.gov.mm/detail?id=B/21624/17&nrc=95773514&off=Y&no=413033"
}Response
{
"offer_url": "openid-credential-offer://?credential_offer_uri=https%3A%2F%2F...",
"credential_type": "MyanmarDriverLicense",
"issued_at": "2025-01-01T00:00:00.000Z"
}curl
curl -X POST https://your-issuer.example/api/public/v1/credentials/issue \
-H "Authorization: Bearer vci_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"source_url":"https://mdl.rtad.gov.mm/detail?id=B/21624/17&nrc=95773514&off=Y&no=413033"}'Mobile flow
On mobile, take offer_url from the response and open it directly — the OS launches the user's wallet app and starts the OpenID4VCI flow with the upstream issuer.
// React Native
import { Linking } from "react-native";
await Linking.openURL(offerUrl);
// iOS / Android web
window.location.href = offerUrl;On desktop or web, render offer_url as a QR code so the user can scan with their wallet.
GET /api/public/v1/allowed-sources
Returns the list of active allow-listed source domains.
Error codes
401 missing_api_key/invalid_api_key400 invalid_request/invalid_url400 missing_required_attribute— scraped page is missing fields the template needs403 url_not_allowed— domain or path not on allow-list404 no_active_template_for_source— source has no Hovi template configured502 source_fetch_failed— could not fetch upstream URL502 issuer_failed— Hovi rejected the issuance request500 parse_failed— parser couldn't extract claims