Skip to main content
Use Sanity through Corsair: one client, typed API calls, and incoming webhooks. Connect with an API token from sanity.io/manage under API > Tokens, plus the project id and the dataset you use most. A Viewer token can read. Writing documents needs Editor. Datasets and webhooks need a token with the Administrator or Developer role. Each call can name another dataset with dataset. Writes follow the Studio’s draft model. documents.create and documents.edit change the draft (drafts.<id>), and readers of published content see nothing until documents.publish. Pass publish: true to do both in one transaction. documents.patch and documents.mutate write the exact ids you give them, so a published id changes the live document at once. Before writing a type you don’t know, call schemas.list. It returns each deployed schema’s types and fields, and the schemaId the Agent Actions need. A project deploys its schema with sanity schema deploy, and the list only shows what was last deployed. The Agent Actions (generate, transform, translate, prompt) use one Sanity AI credit per call and stop with a 429 when the organization’s AI budget runs out. They write to drafts unless forcePublishedWrite is set. noWrite: true returns the result without saving it. Sanity marks these actions experimental, and they run on API version vX. The plugin retries reads after a 5xx or a network failure. It never repeats a write that may have landed. Sanity’s 429 for too many requests means nothing ran, so those are retried for writes too. What you get:
  • 26 typed API operations
  • 1 incoming webhook event types

Setup

1

Install

2

Add the plugin

corsair.ts
With multiTenancy: true, scope calls with corsair.withTenant(id). See Quick start for KEK + Hub keys, and Multi-tenancy for account isolation.
3

Choose authentication

4

Connect a tenant

Mint a connect link and send the tenant to it. Hub hosts the page and delivers the result to your app — see Connect / OAuth.

Example API calls

List the latest published posts
Create a draft post
See the full list on the API page.

Webhooks

Create the webhook with webhooks.create, or under API > Webhooks at sanity.io/manage, and give it a secret. Store the same secret with keys.set_webhook_signature. Corsair keeps one secret per tenant, so all of one tenant’s webhooks must share it. sanity({ webhookSecret }) covers accounts with no stored secret, and a stored one takes precedence. Use that option only in a single-tenant app. Every tenant without a stored secret falls back to it, and then a delivery signed for one tenant also verifies under another’s tenantId. Deliveries without a valid signature are refused. Hand processWebhook the raw body text (await request.text()), because a parsed body cannot verify. A delivery that fails verification makes processWebhook report a failure. Answer it with a 5xx and Sanity retries twice, 30 seconds apart. Signatures more than 15 minutes from now are refused. Deliveries can repeat, so deduplicate by idempotencyKey. The event’s body is the webhook’s GROQ projection, and its operation, document id and dataset come from Sanity’s headers. On Corsair’s cloud, Hub routes each delivery by its sanity-project-id header to the account that stored that project id. In your own handler, processWebhook takes the tenant from ?tenantId= and uses default without it, so in a multi-tenant app give each tenant its own webhook with ?tenantId= on the URL and pass Object.fromEntries(new URL(request.url).searchParams) to processWebhook as the fourth argument. The signature covers the body but not the URL, so give each tenant’s webhook its own secret. A delivery replayed under another tenantId then fails that tenant’s check. A before hook runs ahead of the signature check, so keep side effects in after.
Mount your framework handler once (see Frameworks), then point the provider at that URL. Full event list: Webhooks. Concepts: Webhooks, Hooks.

What’s next

API reference

Every sanity.api.* operation with input and output types.

Webhooks

Event paths, payloads, and webhookHooks examples.

Connect / OAuth

createLink, Hub delivery, and tenant connect flows.

Use with agents

Expose this plugin’s operations as MCP tools.