
Sanity
Two-way sync Sanity documents with Airtable, Notion, Google Sheets, and more. Covers Studio schema deployment, API tokens, supported fields, and publishing.
Sanity Connector Guide
Section titled “Sanity Connector Guide”This guide covers how to connect Whalesync to a Sanity project, what you need to do in Sanity first, and which fields sync.
In Whalesync terms, a Sanity dataset is the base you pick, each document type in your Studio schema is a table, and each document is a record.
Before you connect: deploy your Studio schema
Section titled “Before you connect: deploy your Studio schema”Deploying takes one command in your Sanity Studio project (Studio 3.88 or newer):
npx sanity schema deployRun it as a logged-in Studio developer, or with an Editor-role token in SANITY_AUTH_TOKEN. See Sanity's guide: Schema deployment.
Whenever you change your Studio schema, deploy it again and then refresh the schema in Whalesync so the new fields appear.
Connecting to Sanity
Section titled “Connecting to Sanity”Whalesync connects with a Sanity API token. See Authorize Sanity for the steps to create one.
- In Whalesync, choose Sanity and paste the token.
- If the token can access more than one project, enter the Project ID as well. Robot tokens are usually scoped to one project, so most people can leave it blank.
- Pick the dataset to sync. Datasets without a deployed schema are listed but cannot be selected until you deploy one.
Syncing Data
Section titled “Syncing Data”Every document type in the deployed schema is available as a table, including types that have no documents yet. Nested objects (for example an seo object with metaTitle and metaDescription) appear as separate fields named seo / Meta title, so each part can be mapped on its own.
Supported Fields
Section titled “Supported Fields”Whalesync does not support every Sanity field type yet. If you need one that is missing, reach out and let us know.
| Sanity type | Status | Notes |
|---|---|---|
| String | ✅ Supported | A string with an options.list is offered as a select, but Whalesync does not enforce the list. |
| Text | ✅ Supported | |
| Number | ✅ Supported | |
| Boolean | ✅ Supported | |
| Date | ✅ Supported | Date only, no time. |
| Datetime | ✅ Supported | |
| URL | ✅ Supported | |
| ✅ Supported | ||
| Slug | ✅ Supported | Synced as the slug text. |
| Reference (one target type) | ✅ Supported | Synced as a link to the target document type. Weak references stay weak. |
| Array of references | ✅ Supported | Synced as a multi-link field. |
| Array of strings | ✅ Supported | |
| Portable Text (block content) | ✅ Supported | Synced as HTML, including image and code blocks when your Studio schema allows them. |
| Image | ✅ Supported | Synced as the image's CDN URL. Writing a URL uploads the image to Sanity. |
| File | ✅ Supported | Synced as the file's CDN URL. Writing a URL uploads the file to Sanity. |
| Object | ✅ Supported | Flattened into one field per sub-field, up to three levels deep. Deeper objects are synced as JSON, read only. |
| Reference (several target types) | ➡️ Supported (1-Way) | Read only. Whalesync links point at one table, so the target document id is synced as text. |
| Geopoint | ✅ Supported (as JSON) | Read only. |
| Array of objects or images | ✅ Supported (as JSON) | Read only. |
Fields marked readOnly in the Studio | ➡️ Supported (1-Way) | Read only in Whalesync too. |
| Cross-dataset and global references | ✅ Supported (as JSON) | Read only. |
Additional Fields
Section titled “Additional Fields”Whalesync adds fields that are not part of your Studio schema.
| Field | Explanation | Writable |
|---|---|---|
| Record ID | The document's _id. When creating a document from another app, map this field to choose the id; it cannot be changed afterwards. | Once, on create |
| Status | Draft, Changed, or Published. Shows which versions of the document exist, and setting it publishes the document, keeps your edits unpublished, or unpublishes it. Must be mapped. See Status field. | Yes |
| Created at | The document's _createdAt. | No |
| Updated at | The document's _updatedAt. When a draft exists, this is the draft's timestamp. | No |
Status field
Section titled “Status field”Sanity stores a document's published version and its draft as two separate documents. So you can sync a whole document type to one table in your other app, Whalesync shows the pair as one record and adds a Status field that says which versions exist. When a draft exists, the record shows the draft's values.
Every Sanity table mapping must include Status. Whalesync uses it to tell an edit meant for the live document from one meant for a pending draft, so the field mapping screen shows an error until it's mapped.
| Status | Draft exists? | Published exists? | What it means |
|---|---|---|---|
| Draft | ✅ | ❌ | The document only exists as a draft: it has never been published, or it was unpublished. Your edits go to the draft. To publish it, change Status to Published. |
| Published | ❌ | ✅ | The document is live and hasn't changed since it was last published. Edits from your other app go live right away. To keep edits unpublished, change Status to Changed first. If someone edits the document in the Studio, the Studio creates a draft and Status becomes Changed. |
| Changed | ✅ | ✅ | The document is live, and it has changed since it was last published. Your edits go to the draft. To publish them, change Status to Published. To unpublish the document, change Status to Draft. |
Changing Status
Section titled “Changing Status”| Change | Result |
|---|---|
| Draft → Published | Publishes the document for the first time. |
| Published → Changed | Starts a new version by copying the live document into a draft. Any other edits in the same change go into the draft. Editing in the Studio does this automatically. |
| Changed → Published | Publishes the draft, including any other edits made in the same change, and removes the draft. |
| Published → Draft, or Changed → Draft | Unpublishes the document. It's taken down, and its content, including any pending edits and any other edits in the same change, is kept as a draft. |
| Draft → Changed | Not allowed. Changed means a live document with pending edits, and this one has never been published. |
| Status cleared (empty) | Not allowed. |
Discarding a draft can only be done in the Studio.
When a change isn't allowed, nothing is written to Sanity, and the record shows a sync issue until Status is set to an allowed value. The issue says one of:
- "Status Changed means a published document with unpublished edits, and this document has never been published. Set Status to Draft or Published."
- "A Sanity document's Status can't be empty. Set it to Draft, Changed, or Published."
New records
Section titled “New records”- Status empty or Published: the document is created and published.
- Status Draft: the document is created as a draft.
- Status Changed: not allowed, since a new document has no live version.
Common setups
Section titled “Common setups”- Your other app is the source of truth: keep Status at Published, and every edit goes live.
- Review before publishing: create records with Status set to Draft. An editor reviews and publishes them in the Studio, or you set Status to Published.
- Prepare the next version of a live page: set Status to Changed, edit the record over as many syncs as you like, then set Status to Published to put the edits live.
- Take a page down: set Status to Draft. The content is kept as a draft, so you can publish it again later.
Deleting a record removes both the published document and its draft.
Things to Keep in Mind
Section titled “Things to Keep in Mind”- The deployed schema is the schema. A field you add in Studio code does not exist for Whalesync until you run
npx sanity schema deployagain and refresh the schema in Whalesync. - The token needs the Editor role. A Viewer token can read your dataset but every create, update, and delete fails with a permissions error.
- Sanity refuses to delete a referenced document. If another document holds a strong reference to it, Sanity blocks the delete until the reference is removed or made weak.
- Content Releases are not synced. Documents that only exist inside a release are ignored.
- Studio autosaves as you type, so a document you are editing in the Studio updates its draft many times. Whalesync syncs the latest state.