How to populate inputs on a Sanity site via external API

3 replies
Last updated: Jan 17, 2026
Is it possible to populate input options from an external API? The use case is that we have artworks stored on our own server, and would like to feature certain ones to show on our website’s homepage.
AI Update

Yes, absolutely! You can populate input options from an external API in Sanity. Based on your use case of featuring artworks from your own server, you have a couple of approaches:

Custom Input Component Approach

The most flexible solution is to create a custom input component that fetches data from your external API. Here's how this would work:

import {useEffect, useState} from 'react'
import {set, unset} from 'sanity'
import {Stack, Card, Text, Button} from '@sanity/ui'

function ArtworkSelector(props) {
  const {value, onChange} = props
  const [artworks, setArtworks] = useState([])
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    // Fetch artworks from your external API
    fetch('https://your-server.com/api/artworks')
      .then(res => res.json())
      .then(data => {
        setArtworks(data)
        setLoading(false)
      })
  }, [])

  const handleSelect = (artwork) => {
    onChange(set(artwork))
  }

  if (loading) return <Text>Loading artworks...</Text>

  return (
    <Stack space={3}>
      {artworks.map(artwork => (
        <Card 
          key={artwork.id}
          padding={3}
          border
          selected={value?.id === artwork.id}
        >
          <Button onClick={() => handleSelect(artwork)}>
            {artwork.title}
          </Button>
        </Card>
      ))}
    </Stack>
  )
}

// In your schema
{
  name: 'featuredArtwork',
  type: 'object',
  components: {
    input: ArtworkSelector
  }
}

Dynamic Options with Lists

For simpler cases, you can also use the options.list property in your schema and populate it dynamically when the Studio loads:

// Fetch artworks once during schema setup
const artworks = await fetch('https://your-server.com/api/artworks')
  .then(res => res.json())

// In your schema
{
  name: 'featuredArtwork',
  type: 'string',
  options: {
    list: artworks.map(artwork => ({
      title: artwork.title,
      value: artwork.id
    }))
  }
}

Best Practices

For your specific use case, I'd recommend the custom input component approach because:

  1. Real-time updates: You can refresh the artwork list without reloading Studio
  2. Rich preview: Display artwork images, metadata, or other details
  3. Error handling: Better control over loading states and API errors
  4. Caching: Implement smart caching strategies to avoid excessive API calls

The custom input components documentation provides comprehensive guidance on implementing these components, including how to properly handle the onChange prop using Sanity's PatchEvent system for updating values in the Content Lake.

Show original thread
3 replies

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?