Skip to content

Resolver API Reference

The Universal Manifest resolver at myum.net provides runtime UMID lookup and manifest retrieval. This page is the single authoritative reference for integrating with the resolver.

The resolver is separate from the standards/documentation site at universalmanifest.net. This separation keeps the specification neutral and governance-clean, while runtime resolution concerns are isolated in their own service. See Domain Split for the full rationale.

https://myum.net

All responses include a contract version header:

X-UM-Resolver-Contract: myum-resolver/v0.1

The resolver enables CORS for read-only operations (GET, HEAD, OPTIONS).

Exposed headers (available to browser tooling):

  • ETag
  • Cache-Control
  • Content-Type
  • Location
  • X-UM-Resolver-Contract

GET /health

Returns the resolver’s operational status.

Response: 200 OK

{
"status": "ok",
"contract": "myum-resolver/v0.1"
}

Headers:

HeaderValue
Cache-Controlno-store
Content-Typeapplication/json

Example:

Terminal window
curl -s https://myum.net/health | jq .

GET /.well-known/myum-resolver.json

Returns a machine-readable description of the resolver’s path rules, key patterns, caching behavior, and privacy posture.

Response: 200 OK

Example shape:

{
"contract": "myum-resolver/v0.1",
"resolver": "myum-resolver-skeleton",
"umidPathRule": [
"GET /{UMID_PATH}",
"If path segment starts with \"b64u:\" then remainder is base64url UTF-8 UMID.",
"Otherwise the segment is treated as the UMID directly (URL-decoded)."
],
"kv": {
"binding": "UMID_KV",
"keyPattern": "um:{UMID}"
},
"endpoints": {
"health": "/health",
"resolve": "/{UMID_PATH}"
}
}

Headers:

HeaderValue
Cache-Controlno-store
Content-Typeapplication/json

Example:

Terminal window
curl -s https://myum.net/.well-known/myum-resolver.json | jq .

GET /{UMID_PATH}

Resolves a UMID to its manifest payload. This is the primary endpoint.

Supported methods: GET, HEAD, OPTIONS

OPTIONS returns 204 No Content with CORS headers and Cache-Control: no-store.

UMID_PATH must be exactly one path segment (no additional / separators).

The resolver accepts two encoding formats for that path segment:

  1. Direct mode (default): The path segment is URL-decoded and treated as the UMID.

    GET /urn%3Auuid%3A9b1d0e3f-7c4a-4e8b-a2d5-6f3e8c9d0b1a
  2. b64u: mode (escape hatch): If the first path segment starts with b64u:, the remainder is decoded as base64url UTF-8 UMID bytes. Use this when UMIDs contain characters that conflict with URL path syntax (such as /).

    GET /b64u:dXJuOnV1aWQ6OWIxZDBlM2YtN2M0YS00ZThiLWEyZDUtNmYzZThjOWQwYjFh

If UMID parsing fails, the resolver returns:

{ "error": "bad_request", "message": "..." }

Current message values are:

  • missing UMID
  • unexpected extra path segments
  • invalid b64u UMID encoding
  • invalid UMID encoding
  • empty UMID

200 OK — Manifest payload returned directly.

{
"@context": "https://universalmanifest.net/ns/universal-manifest/v0.1/schema.jsonld",
"@id": "urn:uuid:9b1d0e3f-7c4a-4e8b-a2d5-6f3e8c9d0b1a",
"@type": "um:Manifest",
"manifestVersion": "0.1",
"subject": "did:example:user-12345",
"issuedAt": "2026-01-15T10:00:00Z",
"expiresAt": "2026-01-15T11:00:00Z"
}
HeaderValue
Content-Typeapplication/ld+json; charset=utf-8 (default for resolver-managed payloads)
Cache-Controlpublic, max-age=60
ETagW/"sha256-..." (weak ETag based on response body)
Access-Control-Allow-Origin*
X-UM-Resolver-Contractmyum-resolver/v0.1

304 Not Modified — Returned when the client sends If-None-Match and the ETag matches.

307 Temporary Redirect — The UMID is registered as a redirect to a canonical manifest URL.

HeaderValue
LocationThe canonical URL of the manifest
Access-Control-Allow-Origin*
X-UM-Resolver-Contractmyum-resolver/v0.1
StatusMeaningResponse body
400 Bad RequestMissing or invalid UMID encoding{ "error": "bad_request", "message": "..." }
404 Not FoundUnknown UMID{ "error": "not_found", "umid": "..." }
405 Method Not AllowedMethod other than GET/HEAD/OPTIONS{ "error": "method_not_allowed" }
410 GoneKnown UMID, but revoked{ "error": "revoked", "umid": "..." }
500 Internal Server ErrorCorrupt record or internal failure{ "error": "corrupt_record", "umid": "..." }

Error responses are deterministic and machine-parseable JSON.


HTTP caching is intentionally conservative. The default Cache-Control for successful resolutions is:

Cache-Control: public, max-age=60

Important: HTTP cache headers control transport-layer caching only. Consumers MUST enforce the manifest’s own TTL (expiresAt) for application-level “use” decisions, regardless of HTTP cache status. A manifest that is fresh in the HTTP cache but past its expiresAt timestamp must be rejected.

The resolver supports conditional requests via ETag and If-None-Match for efficient revalidation.


The project uses two domains with distinct responsibilities:

DomainPurpose
universalmanifest.netStandards domain — spec artifacts, documentation, JSON-LD vocabulary, governance
myum.netResolver domain — runtime UMID lookup and manifest retrieval

This separation exists so that:

  • The specification remains neutral and governance-clean.
  • Runtime resolution concerns are isolated from spec hosting.
  • The adoption model mirrors established patterns (spec governance is separate from runtime services).

The resolver assumes resolved manifests are publicly readable. Private or authenticated resolution and access control are out of scope for the current contract version and will be designed as an explicit future profile.


Terminal window
curl -s https://myum.net/urn:uuid:11111111-1111-4111-8111-111111111111 | jq .
Terminal window
curl -s https://myum.net/health | jq .
Terminal window
# First request: get the manifest and its ETag
ETAG=$(curl -sI https://myum.net/urn:uuid:11111111-1111-4111-8111-111111111111 \
| grep -i etag | awk '{print $2}' | tr -d '\r')
# Second request: use If-None-Match for conditional fetch
curl -s -o /dev/null -w "%{http_code}" \
-H "If-None-Match: $ETAG" \
https://myum.net/urn:uuid:11111111-1111-4111-8111-111111111111
# Returns 304 if unchanged, 200 with fresh payload if changed
Terminal window
# Encode the UMID as base64url
UMID="urn:uuid:11111111-1111-4111-8111-111111111111"
B64=$(echo -n "$UMID" | base64 | tr '+/' '-_' | tr -d '=')
curl -s "https://myum.net/b64u:$B64" | jq .
Terminal window
curl -sI https://myum.net/urn:uuid:11111111-1111-4111-8111-111111111111

Expected output includes:

HTTP/2 200
content-type: application/ld+json
cache-control: public, max-age=60
etag: W/"sha256-..."
access-control-allow-origin: *
x-um-resolver-contract: myum-resolver/v0.1

The resolver contract intentionally does not cover:

  • Write APIs (PUT/POST) for manifest storage or registration.
  • DID key resolution — verification material may be obtained out-of-band.
  • Private/authenticated resolution — access control is a separate future profile.
  • Rate limiting — not currently enforced; this may be added in a future contract version.