Response models
Types below come from packages/normalizer and API route serializers. Do not assume fields are always non-null unless noted.
Envelope
Successful responses wrap payloads:
{ "data": { /* ... */ } }Paginated list responses:
{ "data": [ /* ... */ ], "pagination": { "nextCursor": "...", "limit": 50 } }NormalizedAsset
Full object returned by GET /v1/assets/:mint.
| Field | Type | Notes | ||
|---|---|---|---|---|
id | string | Mint address | ||
assetType | enum | nft, programmable_nft, compressed_nft, fungible, semi_fungible, mpl_core, unknown | ||
standard | enum | metaplex, token_2022, bubblegum, spl_token, mpl_core, unknown | ||
name | string \ | null | ||
symbol | string \ | null | ||
description | string \ | null | ||
media | object | See Media | ||
attributes | object | { items: Attribute[], status } | ||
collection | object | Embedded collection ref on the asset — see Collection identity | ||
creators | array | { address, share, verified } | ||
royalties | object | { basisPoints } | ||
ownership | object | { owner, snsDomains? } | ||
metadata | object | On-chain URI + off-chain resolution | ||
diagnostics | object | Completeness signals | ||
source | object | { provider, method? } | ||
tokenProgram | object | Inspection — includes mpl_core for Metaplex Core | ||
permissions | object | Control & permission metadata | ||
extensions | array | Token-2022 extensions | ||
core | object \ | null \ | omitted | Additive MPL Core plugin / control facts |
risk | object | Authority/configuration flags | ||
health | object \ | undefined | Metadata health (optional) |
Ownership (`ownership`)
| Field | Type | Notes | |
|---|---|---|---|
owner | string \ | null | Current asset owner wallet address when known |
snsDomains | string[] \ | omitted | Wallet SNS domain display names (e.g. arcing.sns). Resolved via Bonfida's public HTTP API during asset enrichment. Empty or omitted when none are registered — never an error. |
SNS names use the .sns TLD (formerly .sol). The dashboard also links owners to Magic Eden profile pages using the owner address; those links are UI-only and not part of this object.
Collection identity (`collection`)
Embedded collection reference on a resolved asset. This is **not** marketplace scraping and **not** scam analysis.
| Field | Type | Notes | ||
|---|---|---|---|---|
address | string \ | null | Collection mint / grouping address when known | |
name | string \ | null | Human-readable collection name when resolvable | |
verified | boolean \ | null | On-chain / DAS verification flag when known | |
nameSource | string \ | null \ | omitted | Provenance for name when available |
**nameSource values** (provider-independent source class):
| Value | Meaning |
|---|---|
asset_grouping | Name came with the asset’s collection grouping (e.g. DAS collection metadata) |
collection_metadata | Name from resolving the collection mint’s on-chain / DAS metadata |
offchain_metadata | Name from the collection mint’s off-chain JSON |
persisted_collection | Name from an already-indexed collection record |
unknown | Name present without a classified source |
**Resolution order** when address is known and name is missing:
1. Existing grouping / DAS collection metadata on the asset
2. Persisted / cached collection identity (when available)
3. Nested resolution of the collection mint through the normal resolver stack (bounded depth)
4. Off-chain JSON for the collection mint
Nested collection resolution is **non-fatal** and depth-bounded (default depth 1). If enrichment fails, the asset still returns successfully with collection.address preserved and collection.name left null.
Media (`media`)
| Field | Type | Values | |
|---|---|---|---|
image | string \ | null | Canonical image URI from metadata |
animation | string \ | null | Animation URI |
status | enum | available, partial, missing, unknown |
Metadata (`metadata`)
| Field | Type | Values | |
|---|---|---|---|
uri | string \ | null | On-chain metadata URI |
mutable | boolean \ | null | Update authority can change metadata |
offchain.status | enum | resolved, missing_uri, failed, unsupported | |
offchain.resolvedUri | string \ | null | Fetched URI when resolved |
Diagnostics (`diagnostics`)
| Field | Type | Values |
|---|---|---|
completeness | enum | complete, partial, minimal |
missingFields | string[] | Field names missing |
warnings | string[] | Resolver warning codes |
Diagnostics describe structural completeness — **not** a scam or safety score.
Health (`health`)
| Field | Type | Notes |
|---|---|---|
score | number | 0–100 metadata reliability score |
status | enum | healthy (90–100), warning (70–89), degraded (40–69), critical (0–39) |
issues | array | { code, severity, message, field? } |
checks | object | { passed, warnings, failed } |
Health measures metadata reliability, completeness, and accessibility — **not** fraud detection.
Issue codes include: NAME_MISSING, IMAGE_MISSING, OFFCHAIN_METADATA_FAILED, COLLECTION_UNVERIFIED, METADATA_MUTABLE, IMAGE_RECOVERED, and others defined in HEALTH_ISSUE_CODES.
Inspection
#### tokenProgram
| Field | Type | Values | |
|---|---|---|---|
type | enum | spl_token, token_2022, mpl_core, unknown | |
programId | string \ | null | Program public key |
mpl_core uses program ID CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d. Classic SPL mint/freeze authorities do **not** apply to MPL Core assets — those permission fields remain null (UI may show “Not applicable”).
#### core (optional, MPL Core)
Additive control facts when the asset is Metaplex Core:
| Field | Type | |
|---|---|---|
updateAuthority | string \ | null |
collectionAddress | string \ | null |
plugins | array of { type, authority?, data?, permanent? } | |
permanentPlugins | array | |
delegates | array of { address, role? } |
MPL Core is classified (never unknown for program ID CoREENx…) via DAS interfaces (MplCoreAsset / MplCoreCollection / MplCoreGroup), account-owner detection, and available DAS plugin payloads. Helius getAsset requests showCollectionMetadata: true by default so collection names can arrive in grouping[].collection_metadata without a nested fetch; when the name is still missing, collection-identity enrichment may resolve the collection address non-fatally. This is **classification and control-fact awareness**, not a claim of complete on-chain Core plugin decoding beyond DAS.
#### permissions (Authority Intelligence / Control & Permission Metadata)
Technical on-chain control facts. Presence of an authority does **not** by itself mean an asset is unsafe.
| Field | Type | Typical source | |
|---|---|---|---|
mintAuthority | string \ | null | SPL / Token-2022 mint account |
freezeAuthority | string \ | null | SPL / Token-2022 mint account |
updateAuthority | string \ | null | Metaplex metadata / DAS authorities / Token-2022 token metadata |
permanentDelegate | string \ | null | Token-2022 permanent delegate extension |
**Null vs absent:** Fields are always present on NormalizedAsset. null means the authority is absent, revoked, or not determinable for this asset class (for example classic mint authorities on compressed NFTs). Empty strings are not used.
Compressed NFTs: classic mint/freeze authorities often do not apply the same way; values remain null when not determinable. Update authority may still be available from Metaplex/DAS metadata.
#### extensions
Array of { type: string, data?: object } for Token-2022 extensions (transfer hook, transfer fee, non-transferable, default account state, mint close authority, permanent delegate, token metadata, and others already decoded).
#### risk.flags
Array of { code, severity, message, field? }.
Flag codes (technical capabilities, not malicious/safe assertions):
MINT_AUTHORITY_ACTIVEFREEZE_AUTHORITY_ACTIVEPERMANENT_DELEGATE_ACTIVETRANSFER_HOOK_ACTIVETRANSFER_FEE_CONFIGUREDNON_TRANSFERABLEDEFAULT_ACCOUNT_STATE_FROZENMINT_CLOSE_AUTHORITY_ACTIVEUPDATE_AUTHORITY_PRESENT(informational only — normal for many NFTs)
AssetHealthResponse
GET /v1/assets/:mint/health:
{ "assetId": "...", "health": { /* MetadataHealth */ } }AssetInspectionResponse
GET /v1/assets/:mint/inspection:
{
"assetId": "...",
"tokenProgram": { /* TokenProgram */ },
"permissions": { /* Permissions */ },
"extensions": [ /* TokenExtension */ ],
"risk": { "flags": [ /* RiskFlag */ ] }
}MediaReliabilityResponse
GET /v1/assets/:mint/media — see [media.md](./media.md).
Snapshot models
**Latest** — { mint, snapshotHash, schemaVersion, createdAt, asset }
**History item** — { snapshotHash, healthScore, healthStatus, createdAt }
CollectionEntity
See [collections.md](./collections.md).
CollectionHealthSummary
Aggregated health with separate standards (metadata) and tokenPrograms (on-chain) distributions.
Monitor & event models
See [monitoring.md](./monitoring.md).
HEALTH vs DIAGNOSTICS vs RISK
| Layer | Question it answers |
|---|---|
| **Health** | How reliable and complete is the metadata? |
| **Diagnostics** | Which fields are missing or warned during normalization? |
| **Risk / authority flags** | Which on-chain controls are active? |
These layers are intentionally separate. Good metadata can coexist with active freeze authority or transfer hooks.