DAM & Media8 min read

How to Integrate Uploadcare with Your Headless CMS

Connect Uploadcare to your headless CMS so published images and files get uploaded, transformed, and delivered from Uploadcare's CDN without copy-pasting URLs.

Published April 29, 2026
01Overview

What is Uploadcare?

Uploadcare is a file uploading, image processing, and CDN delivery platform for teams that handle media-heavy web and app experiences. It provides a File Uploader, Upload API, REST API, image transformations, adaptive delivery, and CDN URLs for images, videos, PDFs, and other files. Teams use it when they need browser uploads, remote URL uploads, responsive images, and media processing without building a file pipeline from scratch.


02The case for integration

Why integrate Uploadcare with a headless CMS?

Media workflows get messy fast when content and files live in different places. An editor publishes a product page in one system, downloads an image from another, resizes it in a desktop tool, uploads it to a CDN, then pastes the final URL back into the entry. That works for 10 assets. It breaks when you have 10,000 product images, localized campaign files, partner-submitted PDFs, and multiple frontends that all need different sizes and formats.

Connecting Uploadcare to a headless CMS fixes the handoff. Your content entry can keep the business meaning, like product name, locale, category, author, campaign, and publish status, while Uploadcare handles file upload, transformation, storage, and delivery. Instead of asking editors to remember naming rules or transformation URLs, the integration can create or update Uploadcare files when content changes and store the Uploadcare UUID or CDN URL back on the document.

A headless CMS gives you API access, but structured content and real-time events make the difference. With Sanity's AI Content Operating System, content is typed JSON in the Content Lake, so your integration can query exactly the image, alt text, slug, locale, and related product data Uploadcare needs. Webhooks or Functions can run on publish, update, or delete events, which means you don't need nightly batch jobs or manual media audits just to keep files in sync.


03Architecture

Architecture overview

A typical Uploadcare and Sanity integration starts when an editor publishes or updates a document in Sanity Studio. Sanity writes the structured document to the Content Lake, then a webhook fires on the publish event. The webhook can call your API route, or you can run the same logic in a Sanity Function so the sync runs server-side without a separate queue, cron job, or hosting layer. The handler receives the document ID, then uses @sanity/client and a GROQ query to fetch only the fields Uploadcare needs. For example, a product sync might fetch the product title, slug, locale, main image asset URL, alt text, and referenced brand name in one query. The handler downloads the Sanity asset URL, sends the file bytes or remote URL to Uploadcare using @uploadcare/upload-client or the Upload API, sets store to auto, and optionally attaches metadata such as the Sanity document ID and locale. Uploadcare returns a file UUID. Your sync can patch that UUID and the CDN base URL back into the Sanity document, for example uploadcare.uuid and uploadcare.cdnUrl. The frontend then renders Uploadcare URLs with transformations such as /-/resize/800x/, /-/format/auto/, or /-/quality/smart/. The end user gets the right image size and format from Uploadcare's CDN, while editors keep working in Sanity Studio.


04Use cases

Common use cases

🖼️

Responsive product imagery

Sync product image assets to Uploadcare, store the UUID in Sanity, and render size-specific CDN URLs for PDP, PLP, cart, and email templates.

📤

User-generated media intake

Use Uploadcare's File Uploader for customer or partner uploads, then attach the returned file UUID to structured Sanity documents for review and publishing.

🌎

Localized campaign assets

Connect Sanity locale fields with Uploadcare metadata so regional teams can publish localized hero images, PDFs, and social graphics without duplicating content entries.

On-demand image transformations

Keep one source image in Uploadcare and generate crop, resize, format, and quality variants through CDN URL operations at render time.


05Implementation

Step-by-step integration

  1. 1

    Create your Uploadcare project

    Sign up for Uploadcare, create or open a project, and copy the public key from the Uploadcare dashboard. If your sync needs REST operations such as file deletion or storage changes, also create a secret key and keep it server-side only.

  2. 2

    Install the SDKs

    Install the Uploadcare upload client and Sanity client in the service that will receive webhooks: npm install @uploadcare/upload-client @sanity/client. Add UPLOADCARE_PUBLIC_KEY, SANITY_PROJECT_ID, SANITY_DATASET, and a Sanity token with read and patch permissions to your environment.

  3. 3

    Model Uploadcare fields in Sanity Studio

    Add fields for the original Sanity asset and the Uploadcare result. A common pattern is mainImage for the editor-selected source asset, alt for accessibility text, and an uploadcare object with uuid, cdnUrl, syncedAt, and status fields.

  4. 4

    Create the sync trigger

    Create a Sanity webhook that fires on publish events for the document types that contain media, such as product, article, or campaign. Use a GROQ filter like _type == "product" && defined(mainImage.asset). Point it to your API route, or run equivalent logic in a Sanity Function.

  5. 5

    Upload the file to Uploadcare

    In the handler, fetch the document from Sanity with GROQ, download the Sanity asset URL, and send the bytes to Uploadcare with uploadFile. Store the returned UUID and CDN URL back on the Sanity document so your frontend doesn't need to repeat the sync work.

  6. 6

    Test the frontend output

    Publish one test entry, confirm the Uploadcare UUID appears in Sanity Studio, then render a transformed CDN URL such as https://ucarecdn.com/{uuid}/-/resize/1200x/-/format/auto/. Test missing images, draft updates, deleted files, and republished content before you roll it out.


06Code

Code example

tsapp/api/sanity-uploadcare/route.ts
import {createClient} from '@sanity/client'
import {uploadFile} from '@uploadcare/upload-client'

const sanity = createClient({
  projectId: process.env.SANITY_PROJECT_ID!,
  dataset: process.env.SANITY_DATASET!,
  apiVersion: '2025-01-01',
  token: process.env.SANITY_TOKEN!,
  useCdn: false,
})

export async function POST(req: Request) {
  const {_id} = await req.json()

  const doc = await sanity.fetch(
    `*[_id == $id][0]{
      _id,
      title,
      "assetUrl": mainImage.asset->url
    }`,
    {id: _id.replace(/^drafts\./, '')}
  )

  if (!doc?.assetUrl) return Response.json({skipped: true})

  const asset = await fetch(doc.assetUrl)
  const buffer = Buffer.from(await asset.arrayBuffer())

  const file = await uploadFile(buffer, {
    publicKey: process.env.UPLOADCARE_PUBLIC_KEY!,
    store: 'auto',
    fileName: `${doc._id}.jpg`,
    metadata: {sanityDocumentId: doc._id, title: doc.title || ''},
  })

  await sanity.patch(doc._id).set({
    uploadcare: {
      uuid: file.uuid,
      cdnUrl: `https://ucarecdn.com/${file.uuid}/`,
      syncedAt: new Date().toISOString(),
    },
  }).commit()

  return Response.json({uuid: file.uuid})
}

07Why Sanity

How Sanity + Uploadcare works

Build your Uploadcare integration on Sanity

Sanity's AI Content Operating System gives you structured content, real-time events, and flexible APIs to connect Uploadcare with every channel that needs media.

Start building free →

08Comparison

CMS approaches to Uploadcare

CapabilityTraditional CMSSanity
Media data structureMedia often sits in page fields, server folders, or plugin-specific tables, so Uploadcare sync may need exports or custom parsing.The Content Lake stores typed JSON with references, so a GROQ query can fetch the asset, alt text, SKU, locale, and related brand together.
Sync timingSync often depends on plugin hooks, scheduled jobs, or manual publish steps.Webhooks and Functions can run on publish, update, or delete events, with GROQ filters that limit syncs to entries with media fields.
Uploadcare metadataMetadata such as author, region, product ID, or campaign name may be buried in page content or custom fields.GROQ can join references and project clean metadata for Uploadcare in one request, such as product SKU, locale, slug, and image role.
Frontend deliveryPages may render fixed media URLs, making Uploadcare transformations harder to apply consistently.Store the Uploadcare UUID on the document, then use the same structured field across web, mobile, email, and app frontends.
Editorial controlEditors may need to switch between the page editor, media library, and Uploadcare dashboard to confirm asset status.Sanity Studio is built with React, so you can show Uploadcare sync status, preview transformed CDN URLs, and add retry actions inside the editor.

09Next steps

Keep building

Explore related integrations to complete your content stack.

Ready to try Sanity?

See how Sanity's Content Operating System powers integrations with Uploadcare and 200+ other tools.