Functions

Function handler reference

Reference documentation for the shape of the function wrapper.

Every Function must export a handler. Handlers contain the logic that the Function infrastructure runs when your function is invoked.

Create a function handler with the sanity functions add command. Every handler receives an object containing context and event parameters. The function does not require a return value.

context properties

  • Provides properties for configuring the Sanity client (@sanity/client). Most commonly used to pass details about the invoking project dataset to a client configuration. See the configuring @sanity/client in Functions guide for details.

  • local

    boolean

    The context.local value is set to true for functions invoked with sanity functions test and sanity functions dev. This can be helpful when you want code to only execute in local environments.

    It is undefined for functions in production.

  • The resource type that triggered the function. For Document functions, this would be dataset. For Media Library functions, this would be media-library.

  • The resource ID that triggered the function. For Document functions, this would be the ID of a dataset in the form <project-id>.<dataset-name>. For Media Library functions, this would be the Media Library ID.

  • resources

    object

    An API for looking up other resources declared in the same Blueprint: datasets, functions, CORS origins, projects, roles, and webhooks by name, without hardcoding their IDs.

clientOptions properties

  • projectId

    string

    The ID of the project that triggered this function.

  • dataset

    string

    The dataset name of the project that triggered this function.

    The sanity functions test command won't include a dataset by default. Run with the --dataset flag to pass a dataset to clientOptions. For example: sanity functions test log-event --dataset production

  • apiHost

    string

    Defaults to https://api.sanity.io.

  • token

    string

    A token with access to your Sanity project. It is recommended to define a Robot Token Blueprint resource yourself with explicit permissions and assign the token to your Function resource. For sanity.function.document Functions, this token is automatically generated with the editor role and added to your project when deploying the blueprint. For other function types, you must explicitly define a Robot Token resource. See Using robot tokens with Functions for more details.

    The sanity functions test command won't include a token by default. Run with the --with-user-token flag to pass the logged-in user's token.

    Note: the token is obfuscated in logs for security. You can directly use it to configure the Sanity client or to make API calls.

Example clientOptions

{
  clientOptions: {
    apiHost: 'https://api.sanity.io',
    projectId: 'abc123',
    dataset: 'production',
    token: '***************'
  }
}

resources properties

context.resources gives your function access to the other resources declared in its Blueprint, so you can reference them by name instead of hardcoding IDs that can change between deployments or environments.

It's a callable object rather than a plain record, and supports a few different ways of looking things up:

Look up any resource by name

const resource = context.resources('my-cors-origin')

Searches across all resource types and returns the first resource with a matching name, or undefined if none exists.

Look up a resource by type and name

const ds = context.resources.dataset('my-dataset')
const fn = context.resources.function('my-other-function')
const cors = context.resources.cors('my-cors-origin')
const project = context.resources.project('my-project')
const role = context.resources.role('my-role')
const webhook = context.resources.webhook('my-webhook')

Each of these narrows the lookup to a single resource type and returns undefined if no resource of that type has that name.

Get every resource

const all = context.resources.all()

Returns a flat array of every resource in the Blueprint, regardless of type.

Iterate over every resource

for (const resource of context.resources) {
  console.log(resource.name, resource.type)
}

context.resources is iterable, so you can loop over every resource directly without calling .all() first.

The BlueprintResource shape

Every lookup, whether by name, by type, or through .all() / iteration, returns objects (or undefined) with this shape:

interface BlueprintResource<TType extends string = string> {
  id: string
  name: string
  type: TType
}
  • id

    string

    The resource's unique ID.

  • name

    string

    The name given to the resource in the Blueprint.

  • type

    string

    The resource's type, for example sanity.project.dataset, sanity.project.

Example context.resources

import { documentEventHandler } from '@sanity/functions'

export const handler = documentEventHandler(async ({ context }) => {
  const notificationsDataset = context.resources.dataset('notifications')

  if (!notificationsDataset) {
    console.log('No "notifications" dataset resource found in this Blueprint')
    return
  }

  console.log('Found dataset resource:', notificationsDataset.id)
})

event properties

Contains the shape of the event, which depends on the event:

  • In the case of document and media-library Function events, like publish, the event shape is the document. This will vary based on your schema.
  • In the case of sync-tag-invalidate Function events, the sync tags will be present under event.data.syncTags.

Example document event

{
  data: { 
    _id: '1234',
    _type: 'article',
    title: 'Functions quick start',
    _createdAt: '2025-04-24T16:26:58.901Z',
    _publishedAt: '2025-04-24T16:26:58.901Z',
  }
}

Example sync-tag-invalidate event

{
  data: { 
    syncTags: ['s1:1023', 's3:3021']
  }
}

Example handler

Type support

When you create a new TypeScript function with sanity functions add, you'll be prompted to add types.

If you did not add types as part of the init process, they are available in the @sanity/functions package:

You can then import and use the documentEventHandler helper to provide type support. See the "Example handler" section for implementation details.

Basic usage

Import documentEventHandler.

Pass type for event data

If you need to type event.data, and you know the shape of your incoming data, you can provide it to documentEventHandler.

Type only (TypeScript)

Import the DocumentEventHandler type.

Type only (JavaScript)

Use the @type comment syntax.

Was this page helpful?