Scheduling API
Reference documentation for the Scheduling API.
Paid feature
The Scheduling API is available to users on Growth or higher plans.
With the Scheduling API you can:
- Publish or unpublish individual documents.
- Create, edit, and delete schedules to run at any date in the future.
- Immediately run any existing schedule, which will attempt to publish or unpublish all associated documents.
Info
A schedule is defined as a collection of multiple documents to be published or unpublished at any time in the future.
All requests to the Scheduling API must be authenticated with a bearer token.
Ensure the following Authorization
header is attached to all requests:
Authorization: Bearer <token>
Where <token>
is your own personal API token or a generated Robot token.
All requests must be made over HTTPS. Requests made over HTTP or without authentication will fail.
If you’re creating a custom plugin to be used within the Sanity studio by multiple users, you’ll probably want to use the token of the current logged-in user.
Protip
Sanity Studio provides a client library importable as a React hook, which automatically handles authenticating requests on behalf of the current logged-in user.
// This example assumes execution within Sanity Studio V3
// (e.g. as a plugin or tool)
import {useClient} from 'sanity'
// Fetch all schedules on the `production` datatset` in project `hb6nr9ev`
// This will send a request authenticated against the current logged in user
const client = useClient({apiVersion: '2022-04-01'})
client
.request({
method: 'GET',
uri: `/schedules/hb6nr9ev/production`
})
.then(data => {
// Handle schedule data as you see fit
})
If you’re creating a third-party application or script that handles scheduling operations on behalf of other users, then you’ll likely want to create a Robot token instead, which can be done in your project’s management console.
→ More information on Authentication in Sanity
The following permissions are required for both document (publish and unpublish) and schedule (fetch, create, update, delete and execute) schedule operations:
- Project Details
read
access - Document
publish
access
Gotcha
Schedule operations involving multiple documents are batched into a single transaction. This means that if a transaction involving multiple documents includes even a single document that you don’t have publish access to, the entire transaction will fail.
→ More information on Content Lake API rate limits
401 Unauthorized
An invalid bearer token has been provided.
403 Forbidden
The current project isn’t on a plan that includes the Scheduling API.
or
The provided bearer token has insufficient permissions.
404 Not Found
The requested route could not be found.
5xx Errors
An internal error has occurred in Sanity. Please check our status page for more information.
When publishing documents, the Scheduling API will either:
- Publish the draft of any specified document IDs (if they exist)
- Re-publish the document (if it’s already published and no drafts exist)
Operations that publish existing published documents will touch the document (updating _updatedAt
) as well as trigger any linked webhooks.
When specifying document IDs as part of a document or schedule operation, you need to specify the document ID without the draft.
prefix.
For example, if you have a draft document in your Studio with ID drafts.69c5e394-1141-4cc8-a3a5-1f04addd6f34
, remove draft.
and specify only the ID: 69c5e394-1141-4cc8-a3a5-1f04addd6f34
.
The Scheduling API will always publish drafts of any specified documents if they exist.
Scheduled operations dates must comply with RFC 3339, and they must be in the following format: YYYY-MM-DDTHH:mm:ss.sssZ
The time zone is always UTC+00:00, as indicated by the Z
suffix.
For example, 7:45 p.m. UTC on December 25, 2077 is represented as 2077-12-25T19:45:00.000Z
All dates must be in the future.
Schedules are a unique resource and are linked to, but do not exist within your Sanity project and dataset. It's important to understand the following behavior:
- As schedules are not contained within a project’s dataset, you cannot query them via GROQ or GraphQL.
- Deleting a dataset or project will immediately delete all schedules.
- Deleting a document won’t delete any schedules associated with it.
sanity dataset export
will not include schedules andsanity dataset import
does not support importing schedules.- Server-side copying of datasets does not include schedules.
- When a project is disabled or blocked, all scheduled publishes will invariably fail as mutations will not be allowed on the dataset.
- The Scheduling API doesn’t validate documents prior to publishing. Any documents you publish (either immediately or at a later date as part of a schedule) will always attempt to publish, even if publication would be typically blocked due to custom validation rules in your Sanity Studio.
{
"id": "sch-28L09J9QA0M7ovPrClvXgfuGxXL",
"name": "Example schedule",
"description": "",
"projectId": "hb6nr9ev",
"dataset": "production",
"author": "p-EiESybeCRamQ",
"state": "scheduled",
"stateReason": "created by user",
"documents": [
{
"documentId": "01208c30-0872-465a-9e4d-9b02d8b9cf7d",
"documentType": "article"
}
],
"createdAt": "2022-04-26T13:40:05.559107Z",
"executeAt": "2077-12-15T19:45:05.053Z"
}
Attributes
idstring
Unique identifier for the schedule
authorstring
ID of the user who created this schedule
createdAtstring
Date when the schedule was created (RFC 3339 date in the format YYYY-MM-DDTHH:mm:ss.sssZ)
datasetstring
Sanity dataset name
descriptionstring
A custom description for the schedule
documentsarray of objects
An array of objects containing a key documentId that references a non-draft document ID.
executeAtstring
Date when the schedule will be run (RFC 3339 date in the format
YYYY-MM-DDTHH:mm:ss.sssZ
)namestring
A custom name for the schedule
projectIdstring
Sanity project ID
statestring
The current state of the schedule. Can be either scheduled, succeeded, executing or cancelled. Schedules that fail to run will be marked as cancelled.
stateReasonstring
A description for the current schedule state. If a schedule fails to run, the reason for failure will be displayed here.
Protip
We recommend that you use the newer Actions API publish
and unpublish
actions instead of these endpoints.
Publish any number of documents immediately.
Request body (required)
A JSON array of objects. Each object must contain a key documentId
that references a non-draft document ID.
Example
Immediately publish document with ID aaa3d1dd-30c3-4c79-ab18-e9c2cb586339
Example Request
curl -X "POST" "https://api.sanity.io/v1/publish/hb6nr9ev/production" \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d $'[ { "documentId": "aaa3d1dd-30c3-4c79-ab18-e9c2cb586339" } ]'
Response
// 200 OK (JSON)
{
"transactionId": "AXfzpiiJdFhpbwBLvIGnUb"
}
Unpublish any number of documents immediately.
Request body (required)
A JSON array of objects. Each object must contain a key documentId
containing a non-draft document ID.
Example
Immediately unpublish documents with ID 38eb7eb8-2c13-4229-9465-4434da1a8e90
and 8b859a22-321d-4903-a443-6ffa995d3500
Request
curl -X "POST" "https://api.sanity.io/v1/unpublish/hb6nr9ev/production" \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d $'[ { "documentId": "38eb7eb8-2c13-4229-9465-4434da1a8e90" }, { "documentId": "8b859a22-321d-4903-a443-6ffa995d3500" } ]'
Response
// 200 OK (JSON)
{
"transactionId": "A5Y41hFe5J3wNnB7OGV71r"
}
Fetch all schedules, ordered by createdAt
in reverse chronological order
Params
authorstring
A single user ID to filter returned schedules by.
documentIdsstring
A comma-separated list of document IDs to filter returned schedules by.
offsetnumber
Number to off offset returned schedules by.
limitnumber
Number to limit returned schedules by. A value of 0 will return all schedules.
statestring
Schedule state to filter by. Valid values are succeeded, scheduled, executing or cancelled.
Example
Fetch all succeeded
schedules created by user poLhU1V3X
and limit to a single item.
Request
curl "https://api.sanity.io/v1/schedules/hb6nr9ev/production?state=succeeded&author=poLhU1V3X&limit=1" \ -H 'Authorization: Bearer <token>'
Response
// 200 OK (JSON)
{
"schedules": [
{
"id": "sch-28MRSuc1Ij4xtNa1rNbhTlMAszj",
"name": "My example schedule",
"description": "",
"projectId": "hb6nr9ev",
"dataset": "production",
"author": "poLhU1V3X",
"state": "succeeded",
"stateReason": "execution completed",
"documents": [
{
"documentId": "f28fe6ce-0454-42c2-8a9a-c469fbf79281",
"documentType": "article"
}
],
"createdAt": "2022-04-27T01:54:31.536236Z",
"executeAt": "2022-04-27T01:55:00Z"
}
]
}
Fetch schedules by ID.
Multiple schedule IDs can be specified as a comma-separated list.
Params
authorstring
A single user ID to filter returned schedules by.
documentIdsstring
A comma-separated list of document IDs to filter returned schedules by.
statestring
Schedule state to filter by. Valid values are succeeded, scheduled or cancelled.
Example
Fetch the schedule with ID sch-28MRSuc1Ij4xtNa1rNbhTlMAszj
Request
curl "https://api.sanity.io/v1/schedules/hb6nr9ev/production/sch-28MRSuc1Ij4xtNa1rNbhTlMAszj" \ -H 'Authorization: Bearer <token>'
Response
// 200 OK (JSON)
{
"schedules": [
{
"id": "sch-28MRSuc1Ij4xtNa1rNbhTlMAszj",
"name": "March update",
"description": "",
"projectId": "hb6nr9ev",
"dataset": "production",
"author": "poLhU1V3X",
"state": "succeeded",
"stateReason": "execution completed",
"documents": [
{
"documentId": "f28fe6ce-0454-42c2-8a9a-c469fbf79281",
"documentType": "article"
}
],
"createdAt": "2022-04-27T01:54:31.536236Z",
"executeAt": "2022-04-27T01:55:00Z"
}
]
}
Create a new schedule to publish or unpublish a set of documents.
Request body (required)
A JSON array of objects with the key documents
. Each object must contain a key documentId
that references a non-draft document ID. The object can optionally include a key ifRevisionId
, which must match the document's _rev
value in order to proceed with the publish or unpublish action.
Params
REQUIREDnamestring
A custom name for the schedule.
Make it human-readable and understandable.executeAtstring
Execution date and time of the schedule.
The time is in UTC format with a Z suffix, corresponding to the UTC+00:00 time zone.
Format:YYYY-MM-DDTHH:mm:ss.sssZ
Example:2077-12-25T07:45:00.000Z
descriptionstring
A custom description for the schedule.
It helps understand the purpose of the schedule.action"publish" | "unpublish"
Optional string.
Accepts the following values:publish
unpublish
If
action
has no value, it defaults topublish
.ifRevisionIdstring
Run the schedule only if the document
_rev
value matchesifRevisionId
.
Example
Create a schedule to publish two documents on 25 December 2025.
Request
curl -X "POST" "https://api.sanity.io/v1/schedules/hb6nr9ev/production" \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d $'{ "documents": [ { "documentId": "01208c30-0872-465a-9e4d-9b02d8b9cf7d" }, { "documentId": "9f515369-87f4-4c70-9009-1c9d7a14aec8" } ], "name": "December 2025 release", "description": "Documents to publish at the end of 2025", "executeAt": "2025-12-25T19:45:00.000Z" }'
Response
// 200 OK (JSON)
{
"id": "sch-28MkGjFSYRBSlcKExN2WBnBxtdQ",
"name": "December 2025 release",
"description": "Documents to publish at the end of 2025",
"projectId": "hb6nr9ev",
"dataset": "production",
"author": "p-EiESybeCRamQ",
"state": "scheduled",
"stateReason": "created by user",
"documents": [
{
"documentId": "01208c30-0872-465a-9e4d-9b02d8b9cf7d",
"ifRevisionId": ""
},
{
"documentId": "9f515369-87f4-4c70-9009-1c9d7a14aec8",
"ifRevisionId": ""
}
],
"createdAt": "2022-04-27T04:29:08.668197Z",
"executeAt": "2025-12-25T19:45:00Z"
}
Update an existing schedule.
Params
descriptionstring
A custom description for the schedule.
It helps understand the purpose of the schedule.documentsarray of objects
An array of objects containing a key documentId that references a non-draft document ID.
executeAtstring
Execution date and time of the schedule.
The time is in UTC format with a Z suffix, corresponding to the UTC+00:00 time zone.
Format:YYYY-MM-DDTHH:mm:ss.sssZ
Example:2077-12-25T07:45:00.000Z
namestring
A custom name for the schedule.
Make it human-readable and understandable.statestring
The target state of the schedule. Can only be set to
cancelled
.
Gotcha
Only schedules with a scheduled
state can be marked as cancelled
.
It’s not possible to cancel already completed schedules.
A schedule cannot have its state changed once in a cancelled
state.
Example
Update schedule with ID sch-28MjyBMDGxT5Gxshj4rYtWClbUq
to run on 12:00PM Jan 1, 2077 and publish document with ID 27aef7e9-7c9f-4b67-9c46-d786b54d0624
Request
curl -X "PATCH" "https://api.sanity.io/v1/schedules/hb6nr9ev/production/sch-28MjyBMDGxT5Gxshj4rYtWClbUq" \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json' \ -d $'{ "executeAt": "2077-01-01T12:00:00.000Z", "documents": [ { "documentId": "27aef7e9-7c9f-4b67-9c46-d786b54d0624" } ] }'
Response
// 200 OK with empty body
Run an existing schedule immediately (publish all its documents).
Multiple schedule IDs can be specified as a comma-separated list.
Example
Run schedule with ID sch-26jr9toRuHMfFqdCtHONjHB2nl7
immediately
Request
curl -X "POST" "https://api.sanity.io/v1/schedules/hb6nr9ev/production/sch-26jr9toRuHMfFqdCtHONjHB2nl7/publish" \ -H 'Authorization: Bearer <token>' \ -H 'Content-Type: application/json'
Response
// 200 OK
{
"schedules": [
{
"id": "sch-26jr9toRuHMfFqdCtHONjHB2nl7",
"name": "May release",
"description": "",
"projectId": "hb6nr9ev",
"dataset": "production",
"author": "poLhU1V3X",
"state": "succeeded",
"stateReason": "execution completed",
"documents": [
{
"documentId": "b80b96b7-24dc-4c49-a5c3-340ef1750b8f",
"documentType": "article"
}
],
"createdAt": "2022-03-22T11:14:47.281244Z",
"executeAt": "2022-05-20T11:30:00Z",
"executedAt": "2022-04-27T06:19:53.267576Z",
"transactionId": "AXfzpiiJdFhpbwBLvIYojP"
}
]
}