Skip to content

Concepts

This page explains the five core ideas you need to understand before working with Universal Manifest. Each concept is introduced with a plain-language definition, an explanation of why it matters, and a concrete example.

Here is a minimal Universal Manifest:

{
"@context": "https://universalmanifest.net/ns/universal-manifest/v0.1/schema.jsonld",
"@type": "UniversalManifest",
"@id": "urn:uuid:9b1d0e3f-7c4a-4e8b-a2d5-6f3e8c9d0b1a",
"manifestVersion": "0.1.0",
"subject": "did:example:user-12345",
"issuedAt": "2026-01-15T10:00:00Z",
"expiresAt": "2026-01-15T11:00:00Z"
}

The sections below explain each part.


What it is: The @id field is the manifest’s unique identifier, called a UMID (Universal Manifest Identifier). It is assigned by whatever system creates the manifest. The v0.1 spec recommends using urn:uuid format (a standard URI format for universally unique identifiers), like urn:uuid:9b1d0e3f-....

Why it matters: The UMID is how you refer to a specific manifest. You can use it to fetch the manifest from a resolver (a web service that looks up manifests by their UMID, such as myum.net/{UMID}), log it for auditing, or link to it from other systems.

Example: In the manifest above, the UMID (the unique @id identifier) is urn:uuid:9b1d0e3f-7c4a-4e8b-a2d5-6f3e8c9d0b1a.


What it is: Two timestamp fields — issuedAt and expiresAt — define the window during which a manifest is considered valid. Together, they act as a time-to-live (TTL) for the document.

Why it matters: Systems that receive a manifest must check these timestamps and reject the manifest if it has expired (i.e., the current time is past expiresAt). This prevents stale data from being acted on. It also enables offline use: a system can cache a manifest and trust it until its expiration, without needing to contact the original source.

Example: A manifest issued at 2026-01-15T10:00:00Z with an expiration of 2026-01-15T11:00:00Z is valid for one hour. After 11:00 UTC, any consumer must reject it and fetch a fresh copy.


What it is: Any system that reads a manifest must safely ignore fields it does not recognize. It must not reject the document or throw an error just because a field is unfamiliar.

Why it matters: This is what makes the format forward-compatible. When a newer version of the spec adds new fields, older systems that have not been updated will still work correctly — they simply skip the fields they do not understand. Without this rule, every new field would break every existing implementation.

Example: Suppose v0.2 adds a signature field. A v0.1 consumer receives a manifest that includes "signature": { ... }. The v0.1 consumer does not know what signature means, so it ignores that field and processes the rest of the manifest normally.


What it is: Shards are optional, named sections within a manifest that group related data. You include only the shards relevant to your use case.

Why it matters: Different systems need different data. Rather than defining a single monolithic format that tries to include everything, UM lets you compose a manifest from independent sections. A social app might only need a publicProfile shard, while a device management system might only need a deviceRegistration shard. Each system reads the shards it understands and ignores the rest.

Example: Below is a manifest with two shards (named data sections):

{
"@id": "urn:uuid:9b1d0e3f-...",
"subject": "did:example:user-12345",
"issuedAt": "2026-01-15T10:00:00Z",
"expiresAt": "2026-01-15T11:00:00Z",

The shards (named data sections) entry contains the grouped data:

"shards": {
"publicProfile": {
"displayName": "Alex",
"avatarUrl": "https://example.com/avatar.png"
},
"deviceRegistration": {
"deviceId": "device-abc-123",
"platform": "ios"
}
}
}

A social app reads publicProfile and ignores deviceRegistration. A device management system does the opposite.


What it is: Pointers are URL references to data stored at its authoritative source — the single, definitive location where that data lives. Instead of copying data into the manifest, you link to it.

Why it matters: Data changes. If you copy a user’s profile into a manifest, it goes stale the moment the user updates their profile. Pointers solve this by referencing the authoritative source directly. The consumer fetches the latest version from the source URL when it needs it.

Example: Below shows pointers (URL references to authoritative sources):

{ "pointers": {
"profileSource": "https://id.example.com/users/12345/profile",
"credentialSource": "https://credentials.example.com/vc/67890"
} }

A consumer that needs the user’s profile fetches it from https://id.example.com/users/12345/profile rather than relying on a potentially stale copy.


These concepts are designed to keep the format simple enough that any system can adopt it — across web apps, mobile apps, AR devices, and IoT systems — while still being flexible enough to carry different kinds of data for different use cases.

  • Start with Getting Started -> Quick Start for the step-by-step implementation guide.
  • Read Build Your Own Implementation if you want to implement UM in a language other than TypeScript.
  • Read Getting Started -> What Is Universal Manifest? if you have not already read the overview.
  • Read Getting Started -> Critical Path to see the minimal sequence from v0.1 adoption to production deployment.