Skip to main content
Mediaflow CDN

Integration Patterns

How a typical integration looks end to end, which pattern fits which kind of platform, and the practices that keep an integration robust.

Worked example - Headless CMS integration

A custom field (or "app", "extension") in a headless CMS lets editors pick a Mediaflow asset and stores the resulting CDN URL on a CMS entry. Walked through here for Contentful; the same shape applies to Strapi, Sanity, Storyblok, Hygraph, and most headless CMSes.

What the editor sees

  1. Opens a CMS entry. The "hero image" field is a Mediaflow asset field.

  2. Clicks Browse Mediaflow → a Mediaflow asset picker opens (web component or a custom UI).

  3. Editor picks an image; the picker returns the numeric file id, and the extension resolves {imageId, filename, filetype} via GET /1/file/{id}?fields=mediaId,filename,type (serverId comes from the auth token).

  4. The CMS field saves {resourceId, url} (plus the picker data for display).

  5. The published page renders <img src="{url}?w=1600&f=auto"> - served by the Mediaflow CDN, not by the CMS.

What the integration extension does

Editor picks an asset (numeric file id)
        │
        ▼
GET /1/file/{id}?fields=mediaId,filename,type  → imageId, filename, filetype (type.id)
        │
        ▼
POST /1/cdn/resources       ← server-side dedup on the natural key
        │
        ├─ 200 OK       - match on a completed resource (reused)
        └─ 202 Accepted - new or re-queued
        │
        ▼
Save {resourceId, url} on the CMS field
        │
        ▼
(optional) poll GET /1/cdn/resources/{resourceId} until status=completed
        │
        ▼
Show preview / ready state to the editor

What does NOT need to change in the CMS

  • Published page URLs - the CDN URL is stable across PUT/PATCH.

  • Image transforms per breakpoint - those live in the render layer, not on the CMS field. The CMS stores the canonical URL and defaults; render code appends ?w=…&f=auto per breakpoint.

Common integration patterns

Partner type

What's stored on the partner platform

Where transforms are applied

Headless CMS (Contentful, Strapi, Sanity, Storyblok, …)

Custom field per asset: {resourceId, url, defaults}

Render layer / template (<picture> / <img srcset>)

Traditional CMS (WordPress, Drupal, …)

Block attribute, shortcode, or media-library entry holding the URL

Theme / template

E-commerce (Shopify, Centra, …)

Product / variant image attribute

Storefront theme

Native apps (iOS / Android)

Asset URL on the app's content backend

Client image loader (request the right variant URL)

Newsletter / static-site builder

URL in the template or builder field

Build step, or query params at send time

The integration manages the resource lifecycle. The partner platform stores the stable URL. The render layer appends transform parameters per usage.

Best practices

  • Re-POST is safe. POST is idempotent on (customer, imageId, serverId, cdnId, filename). A resource left at registered by a prior 503 is picked up and re-published by the next call - no manual dedup needed.

  • Store both url and resourceId. URL → embed; resourceId → lifecycle calls.

  • Treat the URL as immutable. It doesn't change across PUT/PATCH - store it once.

  • Keep defaults small. Defaults are the fallback applied when no transform param is sent. Per-breakpoint sizes (srcset entries) belong in the render layer as query/path parameters, not in defaults.

  • Let the edge negotiate format. Leave f unset or auto and the edge picks AVIF, then WebP, from the request's Accept header, and caches each format separately, so every client gets a format it accepts. Negotiation only runs when the request is transformed: a resource without defaults, fetched with no parameters, is served as its stored rendition (WebP for images). GIF sources fall back to PNG for clients that accept neither, see Supported file types.

  • The filename in the URL does not choose the output format. hero.jpg with no parameters returns the stored WebP rendition; set f=jpeg when you need JPEG bytes.

  • Soft-delete on partner-side delete. Skipping DELETE leaves orphan resources behind.

  • Always use GET. HEAD is not served (405).

Mediaflow API

File Selector

Video Player

External