Returns objects changed since a library version. Pull with since=<next_since> until more is false, and store the last next_since. Deletes appear as tombstones with deleted: true. Narrow with kinds.
Auth. A booth device key. Needs the device:read scope. Send X-Folio-Device-Contract; an unsupported version gets 426.
Limits. Responses carry RateLimit-Limit and RateLimit-Remaining; a 429 carries Retry-After.
Auth
Booth device key
Scope
device:read
Operation id
deviceLibraryChanges
Parameters
Parameters
Name
In
Description
since
query
Return what changed after this value. Start at 0 and pass the last next_since you received. (integer, e.g. 400)
kinds
query
Only these kinds of object: song, theme, service_plan or service_record. Repeat the parameter for several. (string)
limit
query
How many items to return, from 1 to 100. (integer, e.g. 100)
{
"status": false,
"message": "the page cursor is not valid",
"error": {
"code": "invalid_argument",
"status": 400,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
401 The key or session is missing, invalid or expired.401 example
{
"status": false,
"message": "That API key is not valid or has expired.",
"error": {
"code": "unauthenticated",
"status": 401,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
403 The credential lacks the scope, the church is suspended, the feature is not in the plan, or the address is not allowed.403 example
{
"status": false,
"message": "That API key does not have the required scope.",
"error": {
"code": "permission_denied",
"status": 403,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
404 The resource is not in this church.404 example
{
"status": false,
"message": "That item is not in this church.",
"error": {
"code": "not_found",
"status": 404,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
409 Conflict, including a duplicate Idempotency-Key still being processed.409 example
{
"status": false,
"message": "A request with this Idempotency-Key is still running.",
"error": {
"code": "conflict",
"status": 409,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
422 A field failed validation, or an Idempotency-Key was reused with a different body.422 example
{
"status": false,
"message": "A field is not valid.",
"error": {
"code": "validation",
"status": 422,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
426 The booth's contract version is no longer supported. Call GET /v1/device/update.426 example
Writes up to 100 objects. Each carries the base_revision you last saw. If someone changed the object meanwhile, its result is a conflict that includes the current object; merge and retry that object. Results come back per object so one conflict does not fail the batch.
Auth. A booth device key. Needs the device:write scope. Send X-Folio-Device-Contract; an unsupported version gets 426.
Limits. Responses carry RateLimit-Limit and RateLimit-Remaining; a 429 carries Retry-After.
Auth
Booth device key
Scope
device:write
Operation id
deviceLibraryPush
Parameters
Parameters
Name
In
Description
Idempotency-Key
header
Makes a retry safe. The same key with the same body replays the first response for 24 hours; the same key with a different body returns 422; a duplicate that is still running returns 409 with Retry-After. Responses that carry a one-time secret are not replayed. (string, e.g. sunday-2026-11-01-upload)
{
"status": false,
"message": "the page cursor is not valid",
"error": {
"code": "invalid_argument",
"status": 400,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
401 The key or session is missing, invalid or expired.401 example
{
"status": false,
"message": "That API key is not valid or has expired.",
"error": {
"code": "unauthenticated",
"status": 401,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
403 The credential lacks the scope, the church is suspended, the feature is not in the plan, or the address is not allowed.403 example
{
"status": false,
"message": "That API key does not have the required scope.",
"error": {
"code": "permission_denied",
"status": 403,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
404 The resource is not in this church.404 example
{
"status": false,
"message": "That item is not in this church.",
"error": {
"code": "not_found",
"status": 404,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
409 Conflict, including a duplicate Idempotency-Key still being processed.409 example
{
"status": false,
"message": "A request with this Idempotency-Key is still running.",
"error": {
"code": "conflict",
"status": 409,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
422 A field failed validation, or an Idempotency-Key was reused with a different body.422 example
{
"status": false,
"message": "A field is not valid.",
"error": {
"code": "validation",
"status": 422,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
426 The booth's contract version is no longer supported. Call GET /v1/device/update.426 example
{
"status": false,
"message": "the page cursor is not valid",
"error": {
"code": "invalid_argument",
"status": 400,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
401 The key or session is missing, invalid or expired.401 example
{
"status": false,
"message": "That API key is not valid or has expired.",
"error": {
"code": "unauthenticated",
"status": 401,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
403 The credential lacks the scope, the church is suspended, the feature is not in the plan, or the address is not allowed.403 example
{
"status": false,
"message": "That API key does not have the required scope.",
"error": {
"code": "permission_denied",
"status": 403,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
404 The resource is not in this church.404 example
{
"status": false,
"message": "That item is not in this church.",
"error": {
"code": "not_found",
"status": 404,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
409 Conflict, including a duplicate Idempotency-Key still being processed.409 example
{
"status": false,
"message": "A request with this Idempotency-Key is still running.",
"error": {
"code": "conflict",
"status": 409,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
422 A field failed validation, or an Idempotency-Key was reused with a different body.422 example
{
"status": false,
"message": "A field is not valid.",
"error": {
"code": "validation",
"status": 422,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
426 The booth's contract version is no longer supported. Call GET /v1/device/update.426 example
Creates or replaces one object. base_revision is the revision you last read (0 to create). A stale revision answers a conflict with the current object so you can merge.
Auth. A booth device key. Needs the device:write scope. Send X-Folio-Device-Contract; an unsupported version gets 426.
Limits. Responses carry RateLimit-Limit and RateLimit-Remaining; a 429 carries Retry-After.
Auth
Booth device key
Scope
device:write
Operation id
deviceLibraryPut
Parameters
Parameters
Name
In
Description
kind required
path
The object kind: song, theme, service_plan or service_record. (string, e.g. song)
id required
path
The object id. (string, e.g. song-amazing-grace)
Idempotency-Key
header
Makes a retry safe. The same key with the same body replays the first response for 24 hours; the same key with a different body returns 422; a duplicate that is still running returns 409 with Retry-After. Responses that carry a one-time secret are not replayed. (string, e.g. sunday-2026-11-01-upload)
{
"status": false,
"message": "the page cursor is not valid",
"error": {
"code": "invalid_argument",
"status": 400,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
401 The key or session is missing, invalid or expired.401 example
{
"status": false,
"message": "That API key is not valid or has expired.",
"error": {
"code": "unauthenticated",
"status": 401,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
403 The credential lacks the scope, the church is suspended, the feature is not in the plan, or the address is not allowed.403 example
{
"status": false,
"message": "That API key does not have the required scope.",
"error": {
"code": "permission_denied",
"status": 403,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
404 The resource is not in this church.404 example
{
"status": false,
"message": "That item is not in this church.",
"error": {
"code": "not_found",
"status": 404,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
409 Conflict, including a duplicate Idempotency-Key still being processed.409 example
{
"status": false,
"message": "A request with this Idempotency-Key is still running.",
"error": {
"code": "conflict",
"status": 409,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
422 A field failed validation, or an Idempotency-Key was reused with a different body.422 example
{
"status": false,
"message": "A field is not valid.",
"error": {
"code": "validation",
"status": 422,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
426 The booth's contract version is no longer supported. Call GET /v1/device/update.426 example
Marks the object deleted by writing a tombstone, so other booths learn of the delete on their next pull. Pass base_revision to avoid deleting a change you have not seen.
Auth. A booth device key. Needs the device:write scope. Send X-Folio-Device-Contract; an unsupported version gets 426.
Limits. Responses carry RateLimit-Limit and RateLimit-Remaining; a 429 carries Retry-After.
Auth
Booth device key
Scope
device:write
Operation id
deviceLibraryDelete
Parameters
Parameters
Name
In
Description
kind required
path
The object kind: song, theme, service_plan or service_record. (string, e.g. song)
id required
path
The object id. (string, e.g. song-amazing-grace)
base_revision
query
The revision you last read. A stale value is refused so you do not delete a change you have not seen. (integer, e.g. 4)
Idempotency-Key
header
Makes a retry safe. The same key with the same body replays the first response for 24 hours; the same key with a different body returns 422; a duplicate that is still running returns 409 with Retry-After. Responses that carry a one-time secret are not replayed. (string, e.g. sunday-2026-11-01-upload)
Responses
200 Success. Delete one library object.200 example
{
"status": false,
"message": "the page cursor is not valid",
"error": {
"code": "invalid_argument",
"status": 400,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
401 The key or session is missing, invalid or expired.401 example
{
"status": false,
"message": "That API key is not valid or has expired.",
"error": {
"code": "unauthenticated",
"status": 401,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
403 The credential lacks the scope, the church is suspended, the feature is not in the plan, or the address is not allowed.403 example
{
"status": false,
"message": "That API key does not have the required scope.",
"error": {
"code": "permission_denied",
"status": 403,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
404 The resource is not in this church.404 example
{
"status": false,
"message": "That item is not in this church.",
"error": {
"code": "not_found",
"status": 404,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
409 Conflict, including a duplicate Idempotency-Key still being processed.409 example
{
"status": false,
"message": "A request with this Idempotency-Key is still running.",
"error": {
"code": "conflict",
"status": 409,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
422 A field failed validation, or an Idempotency-Key was reused with a different body.422 example
{
"status": false,
"message": "A field is not valid.",
"error": {
"code": "validation",
"status": 422,
"request_id": "req_b337770ecebe03b03a88a8998b59263d"
}
}
426 The booth's contract version is no longer supported. Call GET /v1/device/update.426 example