# Nohead - [Introduction](https://docs.nohead.io/index.md): Model your content, write and publish it, and read it from any site or app over a JSON API. - [Get started](https://docs.nohead.io/quickstart.md): Create a project, publish a record and fetch it from your code. - [API keys](https://docs.nohead.io/guides/api-keys.md): Create a key for each site, server or agent, give it only the scopes it needs, and revoke it when it's done. - [Work with agents](https://docs.nohead.io/guides/agents.md): Let AI agents read and change your content and schema next to your team, through the CLI, the MCP server or the API, with every change attributed and reversible. - [Coding agents](https://docs.nohead.io/guides/coding-agents.md): Let coding agents and CI jobs change your schema and content through the nohead CLI, with readable output and a note on every change. - [MCP server](https://docs.nohead.io/guides/mcp.md): Connect agents without a shell, such as chat apps, agent frameworks and automation platforms, to your content with a project API key. - [Content modelling](https://docs.nohead.io/guides/content-modelling.md): Collections, fields and field types, and how to change them safely. - [Field migrations](https://docs.nohead.io/guides/field-migrations.md): Change a field's type, turn lists on or off, or tighten its rules, with a preview of every record before anything changes. - [Schema as code](https://docs.nohead.io/guides/schema-as-code.md): Keep your collections and fields in a YAML file in your repository, review changes as a diff, and apply them from CI. - [Reading content](https://docs.nohead.io/guides/reading-content.md): List, filter, sort and page through records, embed related ones, count them, and keep a copy in sync. - [Writing content](https://docs.nohead.io/guides/writing-content.md): Create and update records, set each kind of field, sync content without duplicates, change many records at once, and delete and restore them. - [Drafts and publishing](https://docs.nohead.io/guides/publishing.md): Publish and unpublish records, hold changes back in a draft, schedule both, and read only published content from your site. - [Revisions and history](https://docs.nohead.io/guides/history.md): See who changed a record, when, through what and why, compare any two versions, revert, redact values that should never have been stored, and read the organization's activity log. - [Assets](https://docs.nohead.io/guides/assets.md): Upload images and files from the web app, the SDKs, the CLI or over HTTP, describe them with alt text, find them, and clean up the ones you no longer need. - [Images and files](https://docs.nohead.io/guides/images.md): Resize, crop and convert images by writing options into their URLs, with no API call per size, and play or download any other file as uploaded. - [API search](https://docs.nohead.io/guides/api-search.md): Search the records of one collection or a whole project from your servers, with filters, sorting and related records. - [Public search](https://docs.nohead.io/guides/public-search.md): Search published records straight against the search engine with a public token, from a browser or a backend, or add InstantSearch. - [Webhooks](https://docs.nohead.io/guides/webhooks.md): Get a signed HTTP request when records, drafts, assets or the schema change, and verify it before you act on it. - [Errors and retries](https://docs.nohead.io/guides/errors-and-retries.md): Read the API's errors, retry without writing twice, stay within rate limits and keep concurrent edits from overwriting each other. - [Members and roles](https://docs.nohead.io/guides/members-and-roles.md): Invite people to your organization, give each a role, change or remove it, and clean up the access people leave behind. - [Plans and usage](https://docs.nohead.io/guides/plans-and-usage.md): See what your organization uses, what happens at a plan's limits, upgrade or cancel, and delete organizations, projects and your account. - [API requests](https://docs.nohead.io/guides/api-requests.md): What counts as an API request, what happens when the month's run out, and how to make the most of them. - [Overview](https://docs.nohead.io/api-reference/overview.md): How every endpoint authenticates, pages, fails and retries. - [List records](https://docs.nohead.io/api-reference/records/list-records.md) - [Create a record](https://docs.nohead.io/api-reference/records/create-a-record.md): Creates an unpublished record (revision 1). - [Get a record](https://docs.nohead.io/api-reference/records/get-a-record.md): Also a soft-deleted record, with `deleted_at` and `purge_after` set, so it can be reviewed and restored. Published-only API keys find published records only. - [Update a record](https://docs.nohead.io/api-reference/records/update-a-record.md): Partial update. Keys present in `data` replace their values; `null` clears one. `409` with detail code `deleted` while the record is soft-deleted: restore it first. With a pending draft the update still applies, and merging the draft later replaces the fields the draft changes. - [Delete a record](https://docs.nohead.io/api-reference/records/delete-a-record.md): Soft-deletes the record: values and history are kept, and it can be restored until `purge_after`. Its schedule is cleared with it: the delete is the change, so there is no `record.unscheduled` event, and restoring the record doesn't bring the schedule back. Its draft's merge waits for a restore. Del… - [Count records](https://docs.nohead.io/api-reference/records/count-records.md): How many records match the filters, which work as in the list. - [Change many records](https://docs.nohead.io/api-reference/records/change-many-records.md): 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… - [Restore a record](https://docs.nohead.io/api-reference/records/restore-a-record.md): Brings a soft-deleted record back; restoring one that isn't deleted changes nothing. `409` when another record took one of its `unique` values meanwhile (detail code `taken`, with that record's `record_id`). - [Get a record's publication](https://docs.nohead.io/api-reference/publishing/get-a-records-publication.md): What is live: since when, by whom, and the revision. `404` with detail code `not_published` while the record is unpublished or deleted. Published-only API keys get `403`: who published is not content. - [Publish a record](https://docs.nohead.io/api-reference/publishing/publish-a-record.md): Makes the record's current content live (`records:write`), as a `publish` revision. Publishing a published record changes nothing, but a live record with a pending draft is `409` with detail code `draft_pending` and its `draft_id`: publishing never merges a draft (`POST /v1/drafts/{id}/merge` does).… - [Unpublish a record](https://docs.nohead.io/api-reference/publishing/unpublish-a-record.md): Takes the record offline (`records:write`), as an `unpublish` revision; its content is kept. Unpublishing an unpublished record changes nothing. - [Get a record's schedule](https://docs.nohead.io/api-reference/publishing/get-a-records-schedule.md): When the record publishes or unpublishes on its own. `404` with detail code `not_scheduled` when it has no schedule and no `last_error`. Published-only API keys get `403`. - [Schedule publishing or unpublishing](https://docs.nohead.io/api-reference/publishing/schedule-publishing-or-unpublishing.md): Publishes (`publish_at`) or unpublishes (`unpublish_at`) the record at a future time (`records:write`). The change is made within a minute of the time, like a manual publish from the scheduler: it has its own revision (`via: scheduler`), webhooks and audit event. `publish_at` needs an unpublished re… - [Cancel a record's schedule](https://docs.nohead.io/api-reference/publishing/cancel-a-records-schedule.md): Clears `publish_at`, `unpublish_at` and `last_error`. Cancelling when there is nothing to clear changes nothing and records no event. - [List scheduled changes](https://docs.nohead.io/api-reference/publishing/list-scheduled-changes.md): Every pending scheduled change of the collection's records, soonest first (`sort=-at` for the latest first): publishes and unpublishes from records' schedules, and merges from drafts' (`draft_id`). One per change, so a record due to publish and later unpublish appears twice. Deleted records have non… - [List a record's revisions](https://docs.nohead.io/api-reference/revisions/list-a-records-revisions.md): The record's history, newest first. Available while the record is soft-deleted. - [Get a revision](https://docs.nohead.io/api-reference/revisions/get-a-revision.md) - [Get a revision by ID](https://docs.nohead.io/api-reference/revisions/get-a-revision-by-id.md): The same revision `GET /v1/records/{record_id}/revisions/{revision}` returns, by the `rev_` ID that webhooks and the activity log give (`revision_id`). Also for a deleted record's revisions. - [Revert to a revision](https://docs.nohead.io/api-reference/revisions/revert-to-a-revision.md): Writes a new `revert` revision whose data is the target revision mapped onto the current schema. With `dry_run=true`, returns a preview and writes nothing; the preview shows the old revision's data, so it also needs `records:read`. - [Compare two revisions](https://docs.nohead.io/api-reference/revisions/compare-two-revisions.md) - [List a record's drafts](https://docs.nohead.io/api-reference/drafts/list-a-records-drafts.md): The record's draft, as a list: a record has at most one for now. Empty while the record is deleted, whose draft is hidden until it is restored. Published-only API keys get `403`. - [Start a draft](https://docs.nohead.io/api-reference/drafts/start-a-draft.md): Starts the record's draft (`records:write`): changes to its content that wait until they are merged, now or at a set time, while the record keeps its current values. `data` takes values as a record update does, validated on what the record would read after the merge. With `from_revision`, the draft… - [List drafts](https://docs.nohead.io/api-reference/drafts/list-drafts.md): The drafts of the collection's records, most recently changed first, for "changes pending" badges: a record's representation is only its content. One record's draft is `GET /v1/records/{record_id}/drafts`. Deleted records' drafts are left out. Published-only API keys get `403`. - [Get a draft](https://docs.nohead.io/api-reference/drafts/get-a-draft.md): The draft, with `data` as the record would read after the merge, so a site's preview route can render it; `expand` embeds what its relation and asset fields point at, as for a record. `404` while the record is deleted. Published-only API keys get `403`. - [Update a draft](https://docs.nohead.io/api-reference/drafts/update-a-draft.md): Changes the draft's values (`records:write`), as a record update does: keys present in `data` replace their values, and `null` clears one. A value set back to the record's drops out of the draft. - [Discard a draft](https://docs.nohead.io/api-reference/drafts/discard-a-draft.md): Discards the draft for good (`records:write`); the record is unchanged. Returns the draft as it was. The activity log keeps that it existed (`draft.discarded`). - [Merge a draft](https://docs.nohead.io/api-reference/drafts/merge-a-draft.md): Applies the draft to its record now (`records:write`), as one `merge` revision that names the draft and its authors, then removes the draft; returns the record. Content only: the record stays live or unpublished as it was, and `published_at` keeps its date. Fields the record changed since the draft… - [Schedule a draft's merge](https://docs.nohead.io/api-reference/drafts/schedule-a-drafts-merge.md): Merges the draft at `merge_at`, a future time (`records:write`), within a minute of it, from the scheduler (`via: scheduler`). The merge uses the draft as it is then. One that can't be made leaves the draft as it is, with `schedule.last_error` (and `draft.schedule_failed`), as does one due while the… - [Cancel a draft's merge](https://docs.nohead.io/api-reference/drafts/cancel-a-drafts-merge.md): Clears `merge_at` and `last_error`; returns the draft. Cancelling when there is nothing to clear changes nothing and records no event. - [List collections](https://docs.nohead.io/api-reference/collections/list-collections.md): The project's collections. With `filter[deleted]=true`, the deleted ones, until they are purged; published-only API keys get `403` for those. - [Create a collection](https://docs.nohead.io/api-reference/collections/create-a-collection.md): Creates a collection, optionally with initial fields, as schema version 1. - [Get a collection](https://docs.nohead.io/api-reference/collections/get-a-collection.md): Also a deleted collection, with `deleted_at` and `purge_after`, so it can be reviewed and restored (published-only API keys: active ones only). Its fields, records and search are `404` until it is restored. - [Update a collection](https://docs.nohead.io/api-reference/collections/update-a-collection.md): Changing the slug breaks clients that address the collection by slug. `409` with detail code `deleted` while the collection is deleted. - [Delete a collection](https://docs.nohead.io/api-reference/collections/delete-a-collection.md): Soft-deletes the collection. Fields, records and history are kept, and it can be restored until `purge_after`. Deleting a deleted collection changes nothing. - [Restore a deleted collection](https://docs.nohead.io/api-reference/collections/restore-a-deleted-collection.md): Brings back a deleted collection, its fields and records as they were. Past its `purge_after` it is being purged: `409` with detail code `purging`. - [Get the schema at a version](https://docs.nohead.io/api-reference/schema-changes/get-the-schema-at-a-version.md): Published-only API keys read only the current version; earlier ones are `403`. - [List schema changes](https://docs.nohead.io/api-reference/schema-changes/list-schema-changes.md): The collection's schema history, newest first. Published-only API keys get `403`. - [Get a schema change](https://docs.nohead.io/api-reference/schema-changes/get-a-schema-change.md): Published-only API keys get `403`. - [List fields](https://docs.nohead.io/api-reference/fields/list-fields.md): The collection's fields, in position order (the record editor's). With `filter[deleted]=true`, its deleted fields, in the order they were created; published-only API keys get `403` for those. - [Add a field](https://docs.nohead.io/api-reference/fields/add-a-field.md): A collection has at most 100 active fields; a 101st is `409`. - [Get a field](https://docs.nohead.io/api-reference/fields/get-a-field.md): A field of a collection, deleted ones included (with `deleted_at` and `purge_after`). Published-only keys can't read deleted fields (`403`). - [Update a field](https://docs.nohead.io/api-reference/fields/update-a-field.md): Changes that keep existing record values valid. After a `key` change the old key keeps working for 6 months as an alias (see `aliases`), so clients have time to move. Changing `type` or `multiple`, or a `configuration` that existing active records would violate, is rejected with `requires_migration`… - [Delete a field](https://docs.nohead.io/api-reference/fields/delete-a-field.md): Soft-deletes the field. Record values are kept and hidden until it is restored, or purged after `purge_after`. Deleting a deleted field changes nothing. - [Get the field order](https://docs.nohead.io/api-reference/fields/get-the-field-order.md): The collection's active fields in order, the order of the record editor and of schema listings. - [Reorder fields](https://docs.nohead.io/api-reference/fields/reorder-fields.md): Puts the collection's active fields in the given order as one schema change. `field_ids` must list every active field exactly once. - [Stop accepting a renamed field's old key](https://docs.nohead.io/api-reference/fields/stop-accepting-a-renamed-fields-old-key.md): Removes an alias before it expires (`schema:write`): clients using the old key stop working at once. Audited as `field.alias_removed`. - [Restore a deleted field](https://docs.nohead.io/api-reference/fields/restore-a-deleted-field.md): Brings a deleted field back with its values. `409` (detail code `duplicate_values`) for a unique field whose values records share now, and for a collection that already has 100 active fields. - [List field migrations](https://docs.nohead.io/api-reference/migrations/list-field-migrations.md): The collection's field migrations, newest first. Published-only API keys get `403`. - [Migrate a field](https://docs.nohead.io/api-reference/migrations/migrate-a-field.md): Changes one of the collection's fields (`field_id`) in a way that rewrites existing record values: its `type`, `multiple`, a stricter `configuration`, a date's `include_time`, or making it `required` with a `backfill` for records that have no value. - [Get a field migration](https://docs.nohead.io/api-reference/migrations/get-a-field-migration.md): Published-only API keys get `403`. - [Cancel a field migration](https://docs.nohead.io/api-reference/migrations/cancel-a-field-migration.md): A pending migration is cancelled at once. A running one stops at its next batch and is rolled back entirely (`cancel_requested_at` is set until then). Finished migrations cannot be cancelled (`409` with detail code `finished`). - [List assets](https://docs.nohead.io/api-reference/assets/list-assets.md): The project's assets, newest first, filtered by `q`, `filter[deleted]` and `filter[content_type]`. Published-only API keys get `403`: sites reach assets through records (`expand=`), one at a time. - [Start an upload](https://docs.nohead.io/api-reference/assets/start-an-upload.md): Step 1 of uploading a file. Returns the pending asset with its `upload`: send the file's bytes with `upload.method` to `upload.url`, with `upload.headers`, before `upload.expires_at`. The bytes go directly to storage, not through this API. Then call `POST /v1/assets/{asset_id}/complete`. - [Complete an upload](https://docs.nohead.io/api-reference/assets/complete-an-upload.md): Step 2 of uploading a file: verifies the uploaded file (it exists, with the declared size and content type), reads image dimensions and marks the asset `ready`. Only ready assets can be used in records. Safe to retry: a ready asset is returned unchanged. `422 upload_missing` means the file has not b… - [Get an asset](https://docs.nohead.io/api-reference/assets/get-an-asset.md): Also a deleted asset, with `deleted_at` and `purge_after`, until it is purged. Published-only API keys find only ready assets that published records use. - [Update an asset](https://docs.nohead.io/api-reference/assets/update-an-asset.md): Rename the asset or set its alt text. The file itself can't change: upload a new asset for that. `alt` is the default wherever the asset is used; an image in rich text keeps its own `alt` once it has one. A change sends `asset.updated` to webhooks; one that changes nothing sends nothing. `409` with… - [Delete an asset](https://docs.nohead.io/api-reference/assets/delete-an-asset.md): Soft-deletes the asset. The original is kept for 30 days, then purged; records that reference it keep the ID. Until then it can be restored, and image URLs already handed out keep working. To remove it sooner, purge it (`POST /v1/assets/{asset_id}/purge`). Deleting a deleted asset changes nothing. - [See where an asset is used](https://docs.nohead.io/api-reference/assets/see-where-an-asset-is-used.md): The undeleted records that use the asset, through an asset field or as an image in a rich text field, in their content or in their pending draft (whose merge needs the asset): how many, how many of them are published with it in their content, and the 10 most recently updated with the fields they use… - [Restore a deleted asset](https://docs.nohead.io/api-reference/assets/restore-a-deleted-asset.md) - [Permanently delete a deleted asset](https://docs.nohead.io/api-reference/assets/permanently-delete-a-deleted-asset.md): Removes a deleted asset's original from storage now, instead of 30 days after the delete, and frees its storage. It cannot be restored. Records that reference it keep the ID, which no longer resolves. Its image URLs stop working within a minute or so (the CDN's copies are cleared), though browsers k… - [Search records](https://docs.nohead.io/api-reference/search/search-records.md): Full-text search in a collection, ranked by relevance (or `sort`). Anyone who can read the collection can search it, and the words match its `searchable` fields. Filters work as in the records list, on `published_at` and on fields marked `filterable` (not on `deleted` or the other timestamps); `sort… - [Search across collections](https://docs.nohead.io/api-reference/search/search-across-collections.md): One ranked list of matching records from the project's collections (or those in `filter[collection]`), matching their `searchable` fields as in a collection search. `filter[published_at][exists]` narrows to published records (`true`) or unpublished ones. - [Get search index status](https://docs.nohead.io/api-reference/search/get-search-index-status.md): Whether the collection's search index is built and up to date. - [Rebuild the search index](https://docs.nohead.io/api-reference/search/rebuild-the-search-index.md): Rebuilds the collection's index from its records in the background. Search keeps working with the current index until the new one is ready. Rarely needed: indexes follow record and schema changes automatically. Limited to a few an hour per collection and per organization (`429`). - [List webhooks](https://docs.nohead.io/api-reference/webhooks/list-webhooks.md): The project's webhooks. With `filter[deleted]=true`, the deleted ones, until they are purged. - [Create a webhook](https://docs.nohead.io/api-reference/webhooks/create-a-webhook.md): Subscribes a URL to events. The response includes the endpoint's first signing `secret`, shown only here; verify deliveries with it (see the `webhooks` section of this document). Rotate it with `POST /v1/webhooks/{webhook_id}/secrets`. - [Get a webhook](https://docs.nohead.io/api-reference/webhooks/get-a-webhook.md): Also a deleted webhook, with `deleted_at` and `purge_after`, so it can be restored. - [Update a webhook](https://docs.nohead.io/api-reference/webhooks/update-a-webhook.md): Change the URL, description, event types, or turn it off (`enabled: false`). `409` with detail code `deleted` while the webhook is deleted. - [Delete a webhook](https://docs.nohead.io/api-reference/webhooks/delete-a-webhook.md): Soft-deletes the webhook: it can be restored until `purge_after`, with its delivery log. Pending deliveries to it fail at their next attempt. Deleting a deleted webhook changes nothing. - [Send a test event](https://docs.nohead.io/api-reference/webhooks/send-a-test-event.md): Sends a `webhook.test` event to this webhook only. `409` with detail code `disabled` if it is disabled. - [List a webhook's secrets](https://docs.nohead.io/api-reference/webhooks/list-a-webhooks-secrets.md): The secrets that sign its deliveries now, oldest first, without their values. - [Rotate a webhook's signing secret](https://docs.nohead.io/api-reference/webhooks/rotate-a-webhooks-signing-secret.md): Adds a secret, shown only in this response. Deliveries are signed with it from now on, and with the secrets before it for 24 hours more (Standard Webhooks sends several signatures), so receivers can switch without rejecting any. Retire an old one sooner with `DELETE /v1/webhook-secrets/{secret_id}`. - [Retire a webhook secret](https://docs.nohead.io/api-reference/webhooks/retire-a-webhook-secret.md): Stops signing deliveries with it now, instead of 24 hours after a newer one was added. The newest secret can't be retired (`409` with detail code `newest_secret`): rotate first. Retiring a retired secret changes nothing. - [Restore a webhook](https://docs.nohead.io/api-reference/webhooks/restore-a-webhook.md): Brings a deleted webhook back, with its settings and secrets, until `purge_after`. Deliveries that came due while it was deleted failed; attempt them again with `POST /v1/webhook-deliveries/{delivery_id}/retry`. Restoring counts against the plan's webhook limit (`402`). - [List deliveries](https://docs.nohead.io/api-reference/deliveries/list-deliveries.md): The webhook's deliveries, newest first. Kept for 30 days. - [Get a delivery](https://docs.nohead.io/api-reference/deliveries/get-a-delivery.md): The delivery with its payload and every attempt. - [Retry a delivery](https://docs.nohead.io/api-reference/deliveries/retry-a-delivery.md): Attempts the delivery again now, whatever its status; the attempt runs in the background, and the delivery's `attempts` show it. `409` with detail code `deleted` if the webhook was deleted. - [List a project's audit events](https://docs.nohead.io/api-reference/audit/list-a-projects-audit-events.md): The project's audit events, newest first. API keys need the `audit:read` scope and see their own project only. - [Check API health](https://docs.nohead.io/api-reference/system/check-api-health.md): Returns the service status. Does not require authentication. - [Get the authenticated principal](https://docs.nohead.io/api-reference/system/get-the-authenticated-principal.md): The user or API key making the request. API key clients use it to discover their project and scopes. - [Get evaluated feature flags](https://docs.nohead.io/api-reference/system/get-evaluated-feature-flags.md): Feature flags evaluated for the caller. Without credentials, only public flags are returned, evaluated without actors (for the marketing website). With credentials, client flags are included, evaluated for the caller: an API key's project, or for the web app the user and the given organization or pr… - [Overview](https://docs.nohead.io/sdks/overview.md): Use the API from TypeScript, Python or Ruby, with pagination, safe retries, uploads and webhook verification. - [TypeScript](https://docs.nohead.io/sdks/typescript.md): @nohead/sdk for Node, Bun, Deno and edge runtimes: install, configure, typed record data and raw responses. - [Python](https://docs.nohead.io/sdks/python.md): nohead on PyPI, sync and async: install, configure, the async client, and the models it returns. - [Ruby](https://docs.nohead.io/sdks/ruby.md): The nohead gem: install, configure, and the objects it returns. - [Overview](https://docs.nohead.io/cli/overview.md): The nohead CLI for developers, CI and coding agents - install, sign in, configure, and read its output. - [Global options](https://docs.nohead.io/cli/commands/global-options.md): Options every nohead command takes, such as --json and --project. - [Sign-in and setup](https://docs.nohead.io/cli/commands/setup.md): nohead login, nohead logout, nohead link, nohead whoami, nohead health, nohead flags. - [Collections](https://docs.nohead.io/cli/commands/collections.md): Manage collections (data models) - [Fields](https://docs.nohead.io/cli/commands/fields.md): Manage a collection's fields. - [Field migrations](https://docs.nohead.io/cli/commands/migrations.md): Follow and cancel field migrations. - [Schema as code](https://docs.nohead.io/cli/commands/schema.md): Keep the project's collections and fields in a file (schema as code) - [Records](https://docs.nohead.io/cli/commands/records.md): Manage records and their history. - [Drafts](https://docs.nohead.io/cli/commands/drafts.md): Changes to a record that wait until they are merged into it, now or later. - [Assets](https://docs.nohead.io/cli/commands/assets.md): Manage the project's files (media) - [Search](https://docs.nohead.io/cli/commands/search.md): nohead search. - [Webhooks](https://docs.nohead.io/cli/commands/webhooks.md): Send signed HTTP requests when content changes. - [Activity log](https://docs.nohead.io/cli/commands/audit.md): nohead audit. - [Export and import](https://docs.nohead.io/cli/commands/export-import.md): nohead export, nohead import. ## OpenAPI Specs - [openapi](/openapi.json) This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.