curl --request POST \
--url https://api.nohead.io/v1/collections/{collection_id}/record-batches \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"record_ids": [
"<string>"
],
"data": {}
}
'import { Nohead } from "@nohead/sdk"
const nohead = new Nohead()
const result = await nohead.records.bulk("posts", {
action: "publish",
record_ids: ["rec_01J9ZQ3F8X"],
})
from nohead import Nohead
nohead = Nohead()
result = nohead.records.bulk("posts", action="publish", record_ids=["rec_01J9ZQ3F8X"])
require "nohead"
nohead = Nohead::Client.new
result = nohead.records.bulk("posts", action: "publish", record_ids: ["rec_01J9ZQ3F8X"])
{
"object": "record_batch",
"action": "publish",
"succeeded": 123,
"failed": 123,
"results": [
{
"id": "<string>",
"status": "succeeded",
"changed": true,
"record": {
"id": "rec_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"object": "record",
"collection_id": "<string>",
"collection": "<string>",
"published_at": "2023-11-07T05:31:56Z",
"revision": 123,
"schema_version": 123,
"history_pruned_through": 123,
"deleted_at": "2023-11-07T05:31:56Z",
"purge_after": "2023-11-07T05:31:56Z",
"data": {
"title": "Introducing Foo",
"body": {
"type": "doc",
"content": []
}
},
"created_at": "2026-09-27T12:00:00.000Z",
"updated_at": "2026-09-27T12:00:00.000Z",
"expanded": {}
}
}
]
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}{
"error": {
"type": "validation_error",
"message": "Record validation failed",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"field": "title",
"code": "required",
"message": "is required"
}
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}Change many records
Publishes, unpublishes, deletes, restores or updates
(update with data, applied to each) up to 100 records. Each record
is changed as if by its own request: one revision per effective
change, with its own audit event, webhook and search update. Records
that fail (not found, invalid, over a plan limit, a live record with
a pending draft for publish) are reported without stopping the
others. Needs records:write.
curl --request POST \
--url https://api.nohead.io/v1/collections/{collection_id}/record-batches \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"record_ids": [
"<string>"
],
"data": {}
}
'import { Nohead } from "@nohead/sdk"
const nohead = new Nohead()
const result = await nohead.records.bulk("posts", {
action: "publish",
record_ids: ["rec_01J9ZQ3F8X"],
})
from nohead import Nohead
nohead = Nohead()
result = nohead.records.bulk("posts", action="publish", record_ids=["rec_01J9ZQ3F8X"])
require "nohead"
nohead = Nohead::Client.new
result = nohead.records.bulk("posts", action: "publish", record_ids: ["rec_01J9ZQ3F8X"])
{
"object": "record_batch",
"action": "publish",
"succeeded": 123,
"failed": 123,
"results": [
{
"id": "<string>",
"status": "succeeded",
"changed": true,
"record": {
"id": "rec_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"object": "record",
"collection_id": "<string>",
"collection": "<string>",
"published_at": "2023-11-07T05:31:56Z",
"revision": 123,
"schema_version": 123,
"history_pruned_through": 123,
"deleted_at": "2023-11-07T05:31:56Z",
"purge_after": "2023-11-07T05:31:56Z",
"data": {
"title": "Introducing Foo",
"body": {
"type": "doc",
"content": []
}
},
"created_at": "2026-09-27T12:00:00.000Z",
"updated_at": "2026-09-27T12:00:00.000Z",
"expanded": {}
}
}
]
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}{
"error": {
"type": "validation_error",
"message": "Record validation failed",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"field": "title",
"code": "required",
"message": "is required"
}
]
}
}{
"error": {
"type": "invalid_request",
"message": "<string>",
"request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
"details": [
{
"code": "<string>",
"message": "<string>",
"field": "<string>",
"usage": 123,
"limit": 123,
"current_revision": 123,
"record_id": "<string>",
"draft_id": "<string>"
}
]
}
}Authorizations
Project-scoped API key, e.g. nohead_sk_k7fz0a9c3m2q_<secret>, or
nohead_pk_… for a published-only key. Used by servers, CI, the CLI
and coding agents.
Headers
A unique value (1-255 printable ASCII characters) that makes retrying
this request safe. The first response (below 500) is stored for 24
hours per user or API key; retries with the same key and the same
request get it again with an Idempotent-Replayed: true header. The
same key with a different request is refused with 400; a retry while
the first request is still running gets 409.
1 - 255First-party client identifier recorded in history (e.g. cli/0.3.1). Informational only.
Optional reason for the change, kept with the record revision, schema
change or field migration it makes (at most 500 characters once
decoded). Percent-encoded UTF-8, as
encodeURIComponent encodes it, so any language fits in a header:
Rettet%20stavefejl%20p%C3%A5%20forsiden. Plain ASCII may be sent
as is. Other bytes are 400.
Path Parameters
Collection ID, or the collection slug when authenticating with an API key.
Query Parameters
How rich text fields read in the records and drafts returned (and in records they embed with expand): document, the stored ProseMirror JSON document; html, an HTML fragment of known elements with every text and attribute escaped, to put in a page as it is; or markdown (GitHub Flavored), which reads back as the same document when written. Images render with their URLs, so they need no expand: in HTML a WebP rendition at most 1600 pixels wide with its width and height (an SVG as itself), in Markdown the asset's image_url. An image whose asset was deleted is left out of HTML, and written as its asset ID in Markdown. Record history keeps documents.
document, html, markdown