Skip to content

Response Envelope

Every response from the inspect endpoint follows a consistent envelope structure. The envelope separates lifecycle truth, data payload, enrichment provenance, and projection metadata into distinct semantic layers.

Envelope Structure

jsonc
{
  // ── Layer 1: Lifecycle Truth ──
  "success": true,                    // boolean — request succeeded
  "responseSource": "fresh",          // "fresh" | "cache" | "inflight"
  "cached": false,                    // boolean — response served from cache

  // ── Layer 2: Processing State (canonical) ──
  "processing": {
    "status": "complete",             // "partial" | "complete"
    "completion": 1,                  // 0.0 → 1.0
    "enrichmentsPending": false,      // boolean
    "enrichmentStatus": "complete",   // mirrors status
    "completedStages": ["semantic", "mediaFormat", "oembed"],
    "pendingStages": []
  },

  // ── Layer 3: Data Payload (profile-projected) ──
  "data": {
    "identity": { /* ... */ },
    "semantic": { /* ... */ },
    "provider": { /* ... */ },        // only for provider-detected URLs
    "playback": { /* ... */ },
    "metadata": { /* ... */ },
    "preview": { /* ... */ },
    "diagnostics": { /* ... */ }      // only in FULL profile
  },

  // ── Layer 4: Enrichment Provenance (immutable) ──
  "enrichmentSources": {
    "semantic": "fresh",
    "mediaFormat": "fresh",
    "oembed": "fresh"
  },

  // ── Layer 5: Projection Metadata ──
  "projection": {
    "profile": "full",
    "hiddenFields": []
  },

  // ── Layer 6: Async Job (when applicable) ──
  "job": {                            // only for 202 responses
    "id": "job_abc123",
    "status": "processing"
  }
}

Semantic Layers

Layer 1 — Lifecycle Truth

FieldTypeDescription
successbooleanWhether the inspection succeeded
responseSourcestringHow this response was fulfilled: "fresh", "cache", or "inflight"
cachedbooleanBinary cache indicator — true only for cache hits

Response source semantics:

ValueHTTP StatuscachedMeaning
fresh200falseFirst-time processing, enrichments ran during this request
cache200trueServed from canonical cache
inflight202falseAttached to an active enrichment lifecycle in progress

Layer 2 — Processing State

Derived exclusively from the canonical enrichment registry. Never influenced by profile, field projection, or formatter visibility.

See Progressive Enrichment for detailed processing state semantics.

Layer 3 — Data Payload

The primary inspection result. Structure varies by media category and profile. Each namespace carries semantic meaning:

NamespaceAlways PresentDescription
identityURL, final URL, canonical URL, MIME type
semanticKind classification, semantic type, title
playbackPlayback strategy, component, embed/stream capabilities
metadataFile metadata + category-specific sub-object
providerProvider onlyProvider name, confidence, detection method
previewVariesThumbnails, placeholders, palette, waveform
diagnosticsFULL onlyPerformance timings, internal metrics
networkDebug onlyRaw headers (requires ?expand=rawHeaders&debug=true)

Layer 4 — Enrichment Provenance

Immutable record of where each enrichment was originally produced. Never mutated by cache hits — responseSource may change to "cache", but enrichmentSources preserves the original provenance.

See Provider Intelligence for provenance semantics.

Layer 5 — Projection Metadata

Declares the active profile and any fields that were intentionally hidden by the projection layer.

jsonc
// FAST direct media — preview is projection-hidden
{
  "projection": {
    "profile": "fast",
    "hiddenFields": ["preview"]
  }
}

// FAST provider media — provider-native preview is visible
{
  "projection": {
    "profile": "fast",
    "hiddenFields": []
  }
}

HTTP Status Codes

StatusConditionProfile
200Inspection complete or served from cacheFAST, FULL, cached STANDARD
202Enrichments still processing, job dispatchedSTANDARD (heavy media)
400Invalid URL or malformed payloadAny
403SSRF protection blocked the requestAny
408Upstream server timeoutAny
413Remote file exceeds size limitAny
502Upstream server returned invalid responseAny

Data Namespace Contracts

identity

jsonc
{
  "identity": {
    "url": "https://youtu.be/GLTTI1NFHus?si=...",       // original input URL
    "finalUrl": "https://youtu.be/GLTTI1NFHus?si=...",   // after redirect resolution
    "canonicalUrl": "https://www.youtube.com/watch?v=GLTTI1NFHus", // normalized form
    "mime": "text/html"                                   // detected MIME type
  }
}

semantic

jsonc
{
  "semantic": {
    "kind": "embed-media",           // "direct-media" | "embed-media" | "webpage"
    "semanticType": "embedded-video", // category-specific type
    "title": "Provider Native Title"  // when available
  }
}

playback

jsonc
{
  "playback": {
    "strategy": "iframe",            // "native" | "iframe"
    "component": "iframe",           // "video" | "audio" | "iframe" | "img"
    "embedUrl": "https://...",       // for iframe strategy
    "streamable": false,             // range request support
    "downloadable": false            // direct download capability
  }
}

metadata

Contains a filename, size, and exactly one category-specific sub-object:

jsonc
// Image
{ "metadata": { "filename": "...", "size": { "bytes": 2048, "formatted": "2 KB" }, "image": { "colorSpace": "srgb", "hasAlpha": false } } }

// Video
{ "metadata": { "filename": "...", "size": { "bytes": 56733664, "formatted": "54.1 MB" }, "video": { "duration": { "seconds": 30, "formatted": "0:30" }, "fps": 24, "bitrate": { "bps": 1000000, "formatted": "1 Mbps" } } } }

// Audio
{ "metadata": { "filename": "...", "size": { "bytes": 1024, "formatted": "1 KB" }, "audio": { "duration": { "seconds": 30, "formatted": "0:30" }, "bitrate": { "bps": 128000, "formatted": "128 kbps" }, "sampleRate": 44100 } } }

Cross-category metadata namespaces are always omitted — video never has metadata.image, audio never has metadata.video.

Infrastructure Documentation — Behavior-Driven, Schema-Governed