{
  "openapi": "3.1.1",
  "info": {
    "title": "Nohead API",
    "version": "1.0.0",
    "summary": "Programmable content and data API.",
    "contact": {
      "name": "Nohead",
      "email": "hello@nohead.io",
      "url": "https://nohead.io"
    },
    "description": "The Nohead API manages projects, collections (your data models), their\nfields, and records (your content), with full version history.\n\n## Authentication\n\nSend `Authorization: Bearer <token>`. Servers, CI and agents use a\nproject API key (`nohead_sk_...`, or `nohead_pk_...` for a published-only\nkey; created in the web app under API keys)\nwith scopes such as `records:read` or `schema:write`. Organization,\nproject, member and API key management need a person signed in to the\nweb app and are not available to API keys.\n\n## Resources and IDs\n\nEvery object has an `object` type, and every resource with an identity of\nits own an opaque, prefixed `id` (`col_`, `fld_`, `rec_`, ...). Record values live under `data`, keyed by each\nfield's `key`. Timestamps are ISO 8601 in UTC. Deleting a record,\ncollection, field, asset or webhook is soft: it can be restored until its\n`purge_after`.\n\n## Lists\n\nLists return `{ \"data\": [...], \"meta\": { \"next_cursor\", \"has_more\" } }`.\nPass `limit` (1-100) and `cursor` to page, and `sort` (prefix `-` for\ndescending). Records also take `filter[<key>]=value`,\n`filter[published_at][exists]=true` and `expand=<relation, asset or\nrich text fields>`.\n\n## Errors\n\nErrors share one envelope: `{ \"error\": { \"type\", \"message\",\n\"request_id\", \"details\" } }`. `details` lists field-level problems as\n`{ \"field\", \"code\", \"message\" }`. Include the `request_id` when asking\nfor support.\n\n## Safe retries and concurrent edits\n\nSend `Idempotency-Key` on any `POST`, `PUT`, `PATCH` or `DELETE` to make retrying\nit safe: the first result is stored for 24 hours and returned again for\nthe same request. Record responses carry the record's revision as an\n`ETag`; send it back as `If-Match` to update only if nobody changed the\nrecord in the meantime (`412` otherwise).\n\n## History\n\nEvery change to a record is a revision, attributed to the person or API\nkey that made it: record revisions can be listed, diffed and reverted,\nand collections keep a schema history. Send `Nohead-Change-Note` to\nrecord why a change was made. Changes that rewrite existing values\n(such as a field's type) are explicit, previewable field migrations.\n\nHow long revisions are kept depends on the organization's plan. Older\nones are removed, but every record keeps its first revision and its\nlast 10; `history_pruned_through` says how far history was removed.\n",
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.nohead.io",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "records",
      "x-group": "Records",
      "description": "Content entries, one at a time or many at once."
    },
    {
      "name": "publishing",
      "x-group": "Publishing",
      "description": "Making records live, now or at a set time, and taking them down."
    },
    {
      "name": "revisions",
      "x-group": "Revisions",
      "description": "A record's history, comparing two revisions, and going back to one."
    },
    {
      "name": "drafts",
      "x-group": "Drafts",
      "description": "Changes to a record that wait to be merged into it, now or at a set time."
    },
    {
      "name": "collections",
      "x-group": "Collections",
      "description": "User-defined data models."
    },
    {
      "name": "schema-changes",
      "x-group": "Schema changes",
      "description": "A collection's schema history, and its schema at any version."
    },
    {
      "name": "fields",
      "x-group": "Fields",
      "description": "Field definitions of a collection."
    },
    {
      "name": "migrations",
      "x-group": "Field migrations",
      "description": "Explicit field changes that rewrite existing record values, with previews."
    },
    {
      "name": "assets",
      "x-group": "Assets",
      "description": "Files stored for a project, uploaded directly to storage."
    },
    {
      "name": "search",
      "x-group": "Search",
      "description": "Full-text search in collections and across a project."
    },
    {
      "name": "webhooks",
      "x-group": "Webhooks",
      "description": "Event notifications sent to your URLs, and the secrets that sign them."
    },
    {
      "name": "deliveries",
      "x-group": "Webhook deliveries",
      "description": "Each event sent to a webhook, its attempts, and retrying it."
    },
    {
      "name": "audit",
      "x-group": "Activity log",
      "description": "The append-only trail of who changed what, through which client."
    },
    {
      "name": "system",
      "x-group": "System",
      "description": "Service status, the caller, and its feature flags."
    }
  ],
  "paths": {
    "/v1/collections/{collection_id}/records": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "records_list",
        "summary": "List records",
        "tags": [
          "records"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/RecordFilter"
          },
          {
            "name": "sort",
            "in": "query",
            "description": "`created_at`, `updated_at`, `published_at` (unpublished records\nfirst), or the key of a text, number, boolean, date or\nenum field with one value (records without a value last, in both\ndirections; text by code point). `-` for descending.\n",
            "schema": {
              "type": "string",
              "pattern": "^-?[a-z][a-z0-9_]*$",
              "default": "-created_at",
              "examples": [
                "-published_at",
                "title",
                "-published_on"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/Expand"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "records_create",
        "summary": "Create a record",
        "description": "Creates an unpublished record (revision 1).\n\nWith `upsert_on`, the field key of a `unique` field whose value\n`data` includes, it updates the active record holding that value\ninstead, if one exists (`200`), as `PATCH /v1/records/{id}` does: keys\nin `data` replace their values. Otherwise it creates one (`201`). So a\ncontent sync can run again without making duplicates. `If-Match`\napplies to the update; with no record to update it is `412`. A\nsoft-deleted record doesn't count: its unique values are free.\n",
        "tags": [
          "records"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/Record"
          },
          "201": {
            "$ref": "#/components/responses/RecordCreated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimitExceeded"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/records/{record_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RecordId"
        }
      ],
      "get": {
        "operationId": "records_get",
        "summary": "Get a record",
        "description": "Also a soft-deleted record, with `deleted_at` and `purge_after` set,\nso it can be reviewed and restored. Published-only API keys find\npublished records only.\n",
        "tags": [
          "records"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/Expand"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Record"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "records_update",
        "summary": "Update a record",
        "description": "Partial update. Keys present in `data` replace their values; `null`\nclears one. `409` with detail code `deleted` while the record is\nsoft-deleted: restore it first. With a pending draft the update still\napplies, and merging the draft later replaces the fields the draft\nchanges.\n",
        "tags": [
          "records"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordWrite"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/Record"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "records_delete",
        "summary": "Delete a record",
        "description": "Soft-deletes the record: values and history are kept, and it can be\nrestored until `purge_after`. Its schedule is cleared with it: the\ndelete is the change, so there is no `record.unscheduled` event, and\nrestoring the record doesn't bring the schedule back. Its draft's\nmerge waits for a restore. Deleting a deleted record changes nothing.\n",
        "tags": [
          "records"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Record"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/records/count": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "records_count",
        "summary": "Count records",
        "description": "How many records match the filters, which work as in the list.",
        "tags": [
          "records"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RecordFilter"
          }
        ],
        "responses": {
          "200": {
            "description": "The count.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordCount"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/record-batches": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "post": {
        "operationId": "records_bulk",
        "summary": "Change many records",
        "description": "Publishes, unpublishes, deletes, restores or updates\n(`update` with `data`, applied to each) up to 100 records. Each record\nis changed as if by its own request: one revision per effective\nchange, with its own audit event, webhook and search update. Records\nthat fail (not found, invalid, over a plan limit, a live record with\na pending draft for `publish`) are reported without stopping the\nothers. Needs `records:write`.\n",
        "tags": [
          "records"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordBatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "What happened to each record, in request order.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordBatch"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/records/{record_id}/restore": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RecordId"
        }
      ],
      "post": {
        "operationId": "records_restore",
        "summary": "Restore a record",
        "description": "Brings a soft-deleted record back; restoring one that isn't deleted\nchanges nothing. `409` when another record took one of its `unique`\nvalues meanwhile (detail code `taken`, with that record's `record_id`).\n",
        "tags": [
          "records"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Record"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimitExceeded"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/records/{record_id}/publication": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RecordId"
        }
      ],
      "get": {
        "operationId": "records_get_publication",
        "summary": "Get a record's publication",
        "description": "What is live: since when, by whom, and the revision. `404` with detail\ncode `not_published` while the record is unpublished or deleted.\nPublished-only API keys get `403`: who published is not content.\n",
        "tags": [
          "publishing"
        ],
        "responses": {
          "200": {
            "description": "The record's publication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordPublication"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "records_publish",
        "summary": "Publish a record",
        "description": "Makes the record's current content live (`records:write`), as a\n`publish` revision. Publishing a published record changes nothing,\nbut a live record with a pending draft is `409` with detail code\n`draft_pending` and its `draft_id`: publishing never merges a draft\n(`POST /v1/drafts/{id}/merge` does). An unpublished record goes live\nwith its current content and keeps its draft.\n",
        "tags": [
          "publishing"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Record"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "records_unpublish",
        "summary": "Unpublish a record",
        "description": "Takes the record offline (`records:write`), as an `unpublish`\nrevision; its content is kept. Unpublishing an unpublished record\nchanges nothing.\n",
        "tags": [
          "publishing"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Record"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/records/{record_id}/schedule": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RecordId"
        }
      ],
      "get": {
        "operationId": "records_get_schedule",
        "summary": "Get a record's schedule",
        "description": "When the record publishes or unpublishes on its own. `404` with detail\ncode `not_scheduled` when it has no schedule and no `last_error`.\nPublished-only API keys get `403`.\n",
        "tags": [
          "publishing"
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/RecordSchedule"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "put": {
        "operationId": "records_schedule",
        "summary": "Schedule publishing or unpublishing",
        "description": "Publishes (`publish_at`) or unpublishes (`unpublish_at`) the record at\na future time (`records:write`). The change is made within a minute of\nthe time, like a manual publish from the scheduler: it has its own\nrevision (`via: scheduler`), webhooks and audit event. `publish_at`\nneeds an unpublished record; `unpublish_at` needs a published record or a\n`publish_at` before it. Setting or cancelling a schedule is audited but\nmakes no revision. `409` with detail code `deleted` while the record is\nsoft-deleted.\n\nReplaces the whole schedule: a time left out, or null, is none, so\nboth left out cancel it as `DELETE` does. Setting the schedule the\nrecord already has changes nothing and records no event. Publishing\nthe record by hand clears `publish_at`, and unpublishing it clears\n`unpublish_at`.\n\nA scheduled change that can't be made when it is due (the record is\nlive with a pending draft, say) is dropped: its time is cleared, the\nschedule's `last_error` says why, and `record.schedule_failed` is\nrecorded. One due while a field migration runs on the collection is\nmade once the migration finishes.\n",
        "tags": [
          "publishing"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordScheduleUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/RecordSchedule"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "records_unschedule",
        "summary": "Cancel a record's schedule",
        "description": "Clears `publish_at`, `unpublish_at` and `last_error`. Cancelling when\nthere is nothing to clear changes nothing and records no event.\n",
        "tags": [
          "publishing"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/RecordSchedule"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/scheduled-changes": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "scheduled_changes_list",
        "summary": "List scheduled changes",
        "description": "Every pending scheduled change of the collection's records, soonest\nfirst (`sort=-at` for the latest first): publishes and unpublishes\nfrom records' schedules, and merges from drafts' (`draft_id`). One per\nchange, so a record due to publish and later unpublish appears twice.\nDeleted records have none. Published-only API keys get `403`.\n",
        "tags": [
          "publishing"
        ],
        "parameters": [
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "at",
                "-at"
              ],
              "default": "at"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of scheduled changes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduledChangeList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/records/{record_id}/revisions": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RecordId"
        }
      ],
      "get": {
        "operationId": "record_revisions_list",
        "summary": "List a record's revisions",
        "description": "The record's history, newest first. Available while the record is soft-deleted.",
        "tags": [
          "revisions"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/RecordRevisionFilter"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of revisions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordRevisionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/records/{record_id}/revisions/{revision}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RecordId"
        },
        {
          "$ref": "#/components/parameters/RevisionNumber"
        }
      ],
      "get": {
        "operationId": "record_revisions_get",
        "summary": "Get a revision",
        "tags": [
          "revisions"
        ],
        "responses": {
          "200": {
            "description": "The revision with its snapshot and changes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordRevisionDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/revisions/{revision_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RevisionId"
        }
      ],
      "get": {
        "operationId": "revisions_get",
        "summary": "Get a revision by ID",
        "description": "The same revision `GET /v1/records/{record_id}/revisions/{revision}`\nreturns, by the `rev_` ID that webhooks and the activity log give\n(`revision_id`). Also for a deleted record's revisions.\n",
        "tags": [
          "revisions"
        ],
        "responses": {
          "200": {
            "description": "The revision with its snapshot and changes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordRevisionDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/records/{record_id}/revisions/{revision}/revert": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RecordId"
        },
        {
          "$ref": "#/components/parameters/RevisionNumber"
        }
      ],
      "post": {
        "operationId": "record_revisions_revert",
        "summary": "Revert to a revision",
        "description": "Writes a new `revert` revision whose data is the target revision mapped\nonto the current schema. With `dry_run=true`, returns a preview and\nwrites nothing; the preview shows the old revision's data, so it also\nneeds `records:read`.\n",
        "tags": [
          "revisions"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "dry_run",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "responses": {
          "200": {
            "description": "The reverted record, or a preview for dry runs.",
            "headers": {
              "ETag": {
                "$ref": "#/components/headers/ETag"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Record"
                    },
                    {
                      "$ref": "#/components/schemas/RevertPreview"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/records/{record_id}/diff": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RecordId"
        }
      ],
      "get": {
        "operationId": "records_diff",
        "summary": "Compare two revisions",
        "tags": [
          "revisions"
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "rich_text",
            "in": "query",
            "description": "How rich text values read in `changes`: `document`, the stored ProseMirror JSON document, or written as `html` or `markdown`, as records read with `rich_text`. Record history and webhooks keep documents. A change that HTML or Markdown can't show (an underline, in Markdown) reads the same on both sides. In HTML and Markdown, text from before a field became rich text reads as paragraphs; an older value that is no document of today's vocabulary, or a redacted one, is kept as stored.",
            "schema": {
              "type": "string",
              "enum": [
                "document",
                "html",
                "markdown"
              ],
              "default": "document"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Changes from one revision to another.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecordDiff"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/records/{record_id}/drafts": {
      "parameters": [
        {
          "$ref": "#/components/parameters/RecordId"
        }
      ],
      "get": {
        "operationId": "record_drafts_list",
        "summary": "List a record's drafts",
        "description": "The record's draft, as a list: a record has at most one for now. Empty\nwhile the record is deleted, whose draft is hidden until it is\nrestored. Published-only API keys get `403`.\n",
        "tags": [
          "drafts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/DraftList"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "drafts_create",
        "summary": "Start a draft",
        "description": "Starts the record's draft (`records:write`): changes to its content\nthat wait until they are merged, now or at a set time, while the\nrecord keeps its current values. `data` takes values as a record\nupdate does, validated on what the record would read after the\nmerge. With `from_revision`, the draft starts from that revision's\nvalues (mapped onto the current schema, as a revert is), to bring an\nearlier version back for review (`400` unless it is a revision\nnumber, `404` if the record has no such revision). Works on any\nrecord, live or not.\n\nOne draft per record: a second is `409` with detail code\n`draft_exists` and its `draft_id`, so change that one instead. `409`\nwith detail code `deleted` while the record is soft-deleted.\n",
        "tags": [
          "drafts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DraftCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "$ref": "#/components/responses/DraftCreated"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/drafts": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "drafts_list",
        "summary": "List drafts",
        "description": "The drafts of the collection's records, most recently changed first,\nfor \"changes pending\" badges: a record's representation is only its\ncontent. One record's draft is `GET /v1/records/{record_id}/drafts`.\nDeleted records' drafts are left out. Published-only API keys get\n`403`.\n",
        "tags": [
          "drafts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "updated_at",
                "-updated_at"
              ],
              "default": "-updated_at"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/DraftList"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/drafts/{draft_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DraftId"
        }
      ],
      "get": {
        "operationId": "drafts_get",
        "summary": "Get a draft",
        "description": "The draft, with `data` as the record would read after the merge, so a\nsite's preview route can render it; `expand` embeds what its relation\nand asset fields point at, as for a record. `404` while the record is\ndeleted. Published-only API keys get `403`.\n",
        "tags": [
          "drafts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/Expand"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Draft"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "drafts_update",
        "summary": "Update a draft",
        "description": "Changes the draft's values (`records:write`), as a record update\ndoes: keys present in `data` replace their values, and `null` clears\none. A value set back to the record's drops out of the draft.\n",
        "tags": [
          "drafts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordWrite"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/Draft"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "drafts_discard",
        "summary": "Discard a draft",
        "description": "Discards the draft for good (`records:write`); the record is\nunchanged. Returns the draft as it was. The activity log keeps that\nit existed (`draft.discarded`).\n",
        "tags": [
          "drafts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Draft"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/drafts/{draft_id}/merge": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DraftId"
        }
      ],
      "post": {
        "operationId": "drafts_merge",
        "summary": "Merge a draft",
        "description": "Applies the draft to its record now (`records:write`), as one `merge`\nrevision that names the draft and its authors, then removes the\ndraft; returns the record. Content only: the record stays live or\nunpublished as it was, and `published_at` keeps its date. Fields the\nrecord changed since the draft started (`base_revision`) keep their\nvalues, unless the draft changes them too. The result is validated\nas a record update is, and unique values are checked again (`422`).\n`If-Match` is the draft's revision; the response's `ETag` is the\nrecord's. Webhooks get `record.updated` with the `draft_id`.\n",
        "tags": [
          "drafts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/IfMatch"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Record"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "412": {
            "$ref": "#/components/responses/PreconditionFailed"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/drafts/{draft_id}/schedule": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DraftId"
        }
      ],
      "put": {
        "operationId": "drafts_schedule",
        "summary": "Schedule a draft's merge",
        "description": "Merges the draft at `merge_at`, a future time (`records:write`),\nwithin a minute of it, from the scheduler (`via: scheduler`). The\nmerge uses the draft as it is then. One that can't be made leaves the\ndraft as it is, with `schedule.last_error` (and `draft.schedule_failed`),\nas does one due while the collection is deleted; one due while a field\nmigration runs on the collection is made once the migration finishes.\nReturns the draft. A merge due while the record is deleted waits;\nonce its time has passed, restoring the record drops it, with\n`last_error`. Setting the time the draft already has changes nothing\nand records no event.\n",
        "tags": [
          "drafts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DraftScheduleUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/Draft"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "drafts_unschedule",
        "summary": "Cancel a draft's merge",
        "description": "Clears `merge_at` and `last_error`; returns the draft. Cancelling when\nthere is nothing to clear changes nothing and records no event.\n",
        "tags": [
          "drafts"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Draft"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/projects/{project_id}/collections": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "get": {
        "operationId": "collections_list",
        "summary": "List collections",
        "description": "The project's collections. With `filter[deleted]=true`, the deleted ones, until they are purged; published-only API keys get `403` for those.",
        "tags": [
          "collections"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DeletedFilter"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of collections.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "collections_create",
        "summary": "Create a collection",
        "description": "Creates a collection, optionally with initial fields, as schema version 1.",
        "tags": [
          "collections"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CollectionCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created collection.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Collection"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimitExceeded"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "collections_get",
        "summary": "Get a collection",
        "description": "Also a deleted collection, with `deleted_at` and `purge_after`, so it\ncan be reviewed and restored (published-only API keys: active ones\nonly). Its fields, records and search are `404` until it is restored.\n",
        "tags": [
          "collections"
        ],
        "responses": {
          "200": {
            "description": "The collection with its active fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Collection"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "collections_update",
        "summary": "Update a collection",
        "description": "Changing the slug breaks clients that address the collection by slug.\n`409` with detail code `deleted` while the collection is deleted.\n",
        "tags": [
          "collections"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CollectionUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated collection.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Collection"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "collections_delete",
        "summary": "Delete a collection",
        "description": "Soft-deletes the collection. Fields, records and history are kept, and\nit can be restored until `purge_after`. Deleting a deleted collection\nchanges nothing.\n",
        "tags": [
          "collections"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "responses": {
          "200": {
            "description": "The deleted collection.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Collection"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/restore": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "post": {
        "operationId": "collections_restore",
        "summary": "Restore a deleted collection",
        "description": "Brings back a deleted collection, its fields and records as they were.\nPast its `purge_after` it is being purged: `409` with detail code\n`purging`.\n",
        "tags": [
          "collections"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "responses": {
          "200": {
            "description": "The restored collection.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Collection"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimitExceeded"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/schema": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "collections_get_schema",
        "summary": "Get the schema at a version",
        "description": "Published-only API keys read only the current version; earlier ones are `403`.",
        "tags": [
          "schema-changes"
        ],
        "parameters": [
          {
            "name": "version",
            "in": "query",
            "description": "Schema version; defaults to the current one.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The full schema definition at that version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Schema"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/schema-changes": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "schema_changes_list",
        "summary": "List schema changes",
        "description": "The collection's schema history, newest first. Published-only API keys get `403`.",
        "tags": [
          "schema-changes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of schema changes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SchemaChangeList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/schema-changes/{schema_change_id}": {
      "parameters": [
        {
          "name": "schema_change_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "operationId": "schema_changes_get",
        "summary": "Get a schema change",
        "description": "Published-only API keys get `403`.",
        "tags": [
          "schema-changes"
        ],
        "responses": {
          "200": {
            "description": "The schema change with before/after definitions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SchemaChangeDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/fields": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "fields_list",
        "summary": "List fields",
        "description": "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.",
        "tags": [
          "fields"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DeletedFilter"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "fields_create",
        "summary": "Add a field",
        "description": "A collection has at most 100 active fields; a 101st is `409`.",
        "tags": [
          "fields"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FieldCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Field"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/fields/{field_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FieldId"
        }
      ],
      "get": {
        "operationId": "fields_get",
        "summary": "Get a field",
        "description": "A field of a collection, deleted ones included (with `deleted_at` and\n`purge_after`). Published-only keys can't read deleted fields (`403`).\n",
        "tags": [
          "fields"
        ],
        "responses": {
          "200": {
            "description": "The field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Field"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "fields_update",
        "summary": "Update a field",
        "description": "Changes that keep existing record values valid. After a `key`\nchange the old key keeps working for 6 months as an alias (see\n`aliases`), so clients have time to move. Changing `type` or `multiple`, or a\n`configuration` that existing active records would violate, is rejected\nwith `requires_migration`: use `POST /v1/collections/{collection_id}/migrations`.\n`409` with detail code `deleted` while the field is deleted.\n",
        "tags": [
          "fields"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FieldUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Field"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "fields_delete",
        "summary": "Delete a field",
        "description": "Soft-deletes the field. Record values are kept and hidden until it is\nrestored, or purged after `purge_after`. Deleting a deleted field\nchanges nothing.\n",
        "tags": [
          "fields"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "responses": {
          "200": {
            "description": "The deleted field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Field"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/field-order": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "fields_get_order",
        "summary": "Get the field order",
        "description": "The collection's active fields in order, the order of the record editor and of schema listings.",
        "tags": [
          "fields"
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/FieldOrder"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "put": {
        "operationId": "fields_reorder",
        "summary": "Reorder fields",
        "description": "Puts the collection's active fields in the given order as one schema\nchange. `field_ids` must list every active field exactly once.\n",
        "tags": [
          "fields"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "field_ids"
                ],
                "properties": {
                  "field_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/FieldOrder"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/fields/{field_id}/aliases/{alias}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FieldId"
        },
        {
          "name": "alias",
          "in": "path",
          "required": true,
          "description": "The old key.",
          "schema": {
            "type": "string"
          }
        }
      ],
      "delete": {
        "operationId": "fields_remove_alias",
        "summary": "Stop accepting a renamed field's old key",
        "description": "Removes an alias before it expires (`schema:write`): clients using the\nold key stop working at once. Audited as `field.alias_removed`.\n",
        "tags": [
          "fields"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "description": "The field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Field"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/fields/{field_id}/restore": {
      "parameters": [
        {
          "$ref": "#/components/parameters/FieldId"
        }
      ],
      "post": {
        "operationId": "fields_restore",
        "summary": "Restore a deleted field",
        "description": "Brings a deleted field back with its values. `409` (detail code\n`duplicate_values`) for a unique field whose values records share\nnow, and for a collection that already has 100 active fields.\n",
        "tags": [
          "fields"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "responses": {
          "200": {
            "description": "The restored field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Field"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/migrations": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "migrations_list",
        "summary": "List field migrations",
        "description": "The collection's field migrations, newest first. Published-only API keys get `403`.",
        "tags": [
          "migrations"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of field migrations.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldMigrationList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "migrations_create",
        "summary": "Migrate a field",
        "description": "Changes one of the collection's fields (`field_id`) in a way that\nrewrites existing record values: its `type`, `multiple`, a stricter\n`configuration`, a date's `include_time`, or making it `required`\nwith a `backfill` for records that have no value.\n\nEvery record is checked first. With `dry_run=true` the result is a\npreview: counts per outcome and sample records, nothing written. Without\nit, a migration whose values do not all convert is refused (`422`)\nunless `on_invalid` is `clear`; otherwise it is accepted (`202`) and\napplied in the background. Poll `GET /v1/migrations/{migration_id}`.\n\nWhile a migration is pending or running, schema writes to the collection\nreturn `409`, and record writes do once it is running (a pending one may\nwait for others to finish). A value written while it waits that does\nnot convert fails the migration, or is cleared with `on_invalid: clear`. Each record whose data changes gets a\n`migrate` revision, so cleared or converted values stay recoverable.\nA dry run's preview shows sample record values, so it also needs\n`records:read`.\n",
        "tags": [
          "migrations"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "dry_run",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          },
          {
            "$ref": "#/components/parameters/ChangeNote"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FieldMigrationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A preview (dry runs only).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldMigrationPreview"
                }
              }
            }
          },
          "202": {
            "description": "The migration was accepted and will be applied in the background.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldMigration"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/migrations/{migration_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MigrationId"
        }
      ],
      "get": {
        "operationId": "migrations_get",
        "summary": "Get a field migration",
        "description": "Published-only API keys get `403`.",
        "tags": [
          "migrations"
        ],
        "responses": {
          "200": {
            "description": "The migration.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldMigration"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/migrations/{migration_id}/cancel": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MigrationId"
        }
      ],
      "post": {
        "operationId": "migrations_cancel",
        "summary": "Cancel a field migration",
        "description": "A pending migration is cancelled at once. A running one stops at its\nnext batch and is rolled back entirely (`cancel_requested_at` is set\nuntil then). Finished migrations cannot be cancelled (`409` with\ndetail code `finished`).\n",
        "tags": [
          "migrations"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "description": "The migration.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldMigration"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/projects/{project_id}/assets": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "get": {
        "operationId": "assets_list",
        "summary": "List assets",
        "description": "The project's assets, newest first, filtered by `q`,\n`filter[deleted]` and `filter[content_type]`. Published-only API keys\nget `403`: sites reach assets through records (`expand=`), one at a\ntime.\n",
        "tags": [
          "assets"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Words that must each appear in the filename or the alt text,\nignoring case: `q=hero jpg` finds `Hero-banner.jpg`. Up to 10\nwords and 200 characters (`400` beyond).\n",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/AssetFilter"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of assets.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "assets_upload",
        "summary": "Start an upload",
        "description": "Step 1 of uploading a file. Returns the pending asset with its `upload`:\nsend the file's bytes with `upload.method` to `upload.url`, with\n`upload.headers`, before `upload.expires_at`. The bytes go directly to\nstorage, not through this API. Then call\n`POST /v1/assets/{asset_id}/complete`.\n\n`content_type` and `byte_size` must be the file's; storage refuses another\ncontent type and completion refuses another size. A file larger than the\nplan allows (10 MB on Free, 100 MB on paid plans) is refused with\n`402 plan_limit_exceeded`, whose details give its size (`usage`) and\nthe limit (`limit`) for `byte_size`.\n\nThe file counts toward the organization's storage from here on, while it\nuploads too. On plans where storage is a hard limit (Free), a file that\nwould go over it is refused with `402 plan_limit_exceeded`; on others,\n`Nohead-Usage-Warning` reports going over.\n\nA project can have at most 100 uploads in progress (started within the\nupload's lifetime, not yet completed or deleted); past that, `409` with\n`too_many_uploads`. Uploads never completed are removed after a day.\n",
        "tags": [
          "assets"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssetUploadCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "headers": {
              "Nohead-Usage-Warning": {
                "$ref": "#/components/headers/UsageWarning"
              }
            },
            "description": "The pending asset, with where to upload it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetWithUpload"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimitExceeded"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/assets/{asset_id}/complete": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AssetId"
        }
      ],
      "post": {
        "operationId": "assets_complete",
        "summary": "Complete an upload",
        "description": "Step 2 of uploading a file: verifies the uploaded file (it exists, with the\ndeclared size and content type), reads image dimensions and marks the asset\n`ready`. Only ready assets can be used in records. Safe to retry: a ready\nasset is returned unchanged. `422 upload_missing` means the file has not\nbeen uploaded yet; `422 upload_mismatch` means it differed from what was\ndeclared, and the asset is marked `failed` (completing it again is\n`409 upload_failed`: start a new upload). `409 upload_changed` if the\nfile was uploaded again while it was being checked: complete it again.\nWebhooks get `asset.created` now, when the asset is ready.\n",
        "tags": [
          "assets"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "description": "The ready asset.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/assets/{asset_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AssetId"
        }
      ],
      "get": {
        "operationId": "assets_get",
        "summary": "Get an asset",
        "description": "Also a deleted asset, with `deleted_at` and `purge_after`, until it is\npurged. Published-only API keys find only ready assets that published\nrecords use.\n",
        "tags": [
          "assets"
        ],
        "responses": {
          "200": {
            "description": "The asset.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "assets_update",
        "summary": "Update an asset",
        "description": "Rename the asset or set its alt text. The file itself can't change:\nupload a new asset for that. `alt` is the default wherever the asset\nis used; an image in rich text keeps its own `alt` once it has one.\nA change sends `asset.updated` to webhooks; one that changes nothing\nsends nothing. `409` with detail code `deleted` while the asset is\ndeleted.\n",
        "tags": [
          "assets"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssetUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The asset.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "assets_delete",
        "summary": "Delete an asset",
        "description": "Soft-deletes the asset. The original is kept for 30 days, then purged;\nrecords that reference it keep the ID. Until then it can be restored,\nand image URLs already handed out keep working. To remove it sooner,\npurge it (`POST /v1/assets/{asset_id}/purge`). Deleting a deleted asset\nchanges nothing.\n",
        "tags": [
          "assets"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "description": "The deleted asset.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/assets/{asset_id}/usage": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AssetId"
        }
      ],
      "get": {
        "operationId": "assets_usage",
        "summary": "See where an asset is used",
        "description": "The undeleted records that use the asset, through an asset field or\nas an image in a rich text field, in their content or in their\npending draft (whose merge needs the asset): how many, how many of\nthem are published with it in their content, and the 10 most\nrecently updated with the fields they use it in. Record history does\nnot count. Needs `records:read` too, as it shows records;\npublished-only API keys get `403`.\n",
        "tags": [
          "assets"
        ],
        "responses": {
          "200": {
            "description": "Where the asset is used.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetUsage"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/assets/{asset_id}/restore": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AssetId"
        }
      ],
      "post": {
        "operationId": "assets_restore",
        "summary": "Restore a deleted asset",
        "tags": [
          "assets"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "description": "The restored asset.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/assets/{asset_id}/purge": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AssetId"
        }
      ],
      "post": {
        "operationId": "assets_purge",
        "summary": "Permanently delete a deleted asset",
        "description": "Removes a deleted asset's original from storage now, instead of 30\ndays after the delete, and frees its storage. It cannot be restored.\nRecords that reference it keep the ID, which no longer resolves. Its\nimage URLs stop working within a minute or so (the CDN's copies are\ncleared), though browsers keep copies they already cached. An asset\nthat is not deleted is `409 not_deleted`: delete it first.\n",
        "tags": [
          "assets"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "description": "The purged asset, as it was.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/search": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "collections_search",
        "summary": "Search records",
        "description": "Full-text search in a collection, ranked by relevance (or `sort`).\nAnyone who can read the collection can search it, and the words match\nits `searchable` fields. Filters work as in the records list,\non `published_at` and on fields marked `filterable`\n(not on `deleted` or the other timestamps); `sort` on `created_at`, `updated_at`, `published_at` and\nfields marked `sortable` (`-` for descending).\nResults are the current records; changes appear within seconds. At\nmost the first 1,000 hits can be paged through. `expand` embeds related\nrecords and assets as in the records list. `409` with a detail code:\n`index_building` while a new collection's index is first built, and\n`rebuilding` when filtering or sorting on a field newly made\n`filterable` or `sortable`, or searching words while the index is\nrebuilt for a field's new key, until the rebuild that adds it has run\n(the index status is `stale` meanwhile).\n",
        "tags": [
          "search"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "name": "q",
            "in": "query",
            "description": "The words to search for; empty matches everything.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/RecordFilter"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "example": "-published_at"
          },
          {
            "$ref": "#/components/parameters/Expand"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of matching records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResults"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/projects/{project_id}/search": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "get": {
        "operationId": "projects_search",
        "summary": "Search across collections",
        "description": "One ranked list of matching records from the project's collections (or\nthose in `filter[collection]`), matching their `searchable` fields as\nin a collection search. `filter[published_at][exists]`\nnarrows to published records (`true`) or unpublished ones.\n",
        "tags": [
          "search"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RichText"
          },
          {
            "name": "q",
            "in": "query",
            "description": "The words to search for; empty matches everything.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "filter",
            "in": "query",
            "style": "deepObject",
            "explode": true,
            "schema": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "collection": {
                  "description": "A collection slug or ID (`filter[collection]=posts`), or up\nto 100 of them (`filter[collection][in]=posts,pages`).\n",
                  "oneOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "in"
                      ],
                      "properties": {
                        "in": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                },
                "published_at": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "exists"
                  ],
                  "properties": {
                    "exists": {
                      "type": "string",
                      "enum": [
                        "true",
                        "false"
                      ]
                    }
                  }
                }
              }
            },
            "examples": {
              "published_posts": {
                "summary": "Published posts and pages",
                "value": {
                  "collection": {
                    "in": "posts,pages"
                  },
                  "published_at": {
                    "exists": "true"
                  }
                }
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of matching records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResults"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/search-index": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "get": {
        "operationId": "search_index_get",
        "summary": "Get search index status",
        "description": "Whether the collection's search index is built and up to date.",
        "tags": [
          "search"
        ],
        "responses": {
          "200": {
            "description": "The index status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchIndex"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/collections/{collection_id}/search-index/rebuild": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CollectionRef"
        }
      ],
      "post": {
        "operationId": "search_index_rebuild",
        "summary": "Rebuild the search index",
        "description": "Rebuilds the collection's index from its records in the background.\nSearch keeps working with the current index until the new one is ready.\nRarely needed: indexes follow record and schema changes automatically.\nLimited to a few an hour per collection and per organization (`429`).\n",
        "tags": [
          "search"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "202": {
            "description": "The rebuild was queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchIndex"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/projects/{project_id}/webhooks": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "get": {
        "operationId": "webhooks_list",
        "summary": "List webhooks",
        "description": "The project's webhooks. With `filter[deleted]=true`, the deleted ones, until they are purged.",
        "tags": [
          "webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DeletedFilter"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of webhooks.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "webhooks_create",
        "summary": "Create a webhook",
        "description": "Subscribes a URL to events. The response includes the endpoint's first\nsigning `secret`, shown only here; verify deliveries with it (see the\n`webhooks` section of this document). Rotate it with\n`POST /v1/webhooks/{webhook_id}/secrets`.\n",
        "tags": [
          "webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The webhook, with its signing secret.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimitExceeded"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "operationId": "webhooks_get",
        "summary": "Get a webhook",
        "description": "Also a deleted webhook, with `deleted_at` and `purge_after`, so it can be restored.",
        "tags": [
          "webhooks"
        ],
        "responses": {
          "200": {
            "description": "The webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "patch": {
        "operationId": "webhooks_update",
        "summary": "Update a webhook",
        "description": "Change the URL, description, event types, or turn it off (`enabled: false`).\n`409` with detail code `deleted` while the webhook is deleted.\n",
        "tags": [
          "webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "webhooks_delete",
        "summary": "Delete a webhook",
        "description": "Soft-deletes the webhook: it can be restored until `purge_after`, with\nits delivery log. Pending deliveries to it fail at their next attempt.\nDeleting a deleted webhook changes nothing.\n",
        "tags": [
          "webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "description": "The deleted webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}/test": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "operationId": "webhooks_test",
        "summary": "Send a test event",
        "description": "Sends a `webhook.test` event to this webhook only. `409` with detail\ncode `disabled` if it is disabled.\n",
        "tags": [
          "webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "202": {
            "description": "The queued delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDelivery"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}/secrets": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "operationId": "webhook_secrets_list",
        "summary": "List a webhook's secrets",
        "description": "The secrets that sign its deliveries now, oldest first, without their values.",
        "tags": [
          "webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of secrets.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSecretList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "webhooks_rotate_secret",
        "summary": "Rotate a webhook's signing secret",
        "description": "Adds a secret, shown only in this response. Deliveries are signed with\nit from now on, and with the secrets before it for 24 hours more\n(Standard Webhooks sends several signatures), so receivers can switch\nwithout rejecting any. Retire an old one sooner with\n`DELETE /v1/webhook-secrets/{secret_id}`.\n",
        "tags": [
          "webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "201": {
            "description": "The new secret, with its value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSecretWithValue"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/webhook-secrets/{secret_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookSecretId"
        }
      ],
      "delete": {
        "operationId": "webhook_secrets_retire",
        "summary": "Retire a webhook secret",
        "description": "Stops signing deliveries with it now, instead of 24 hours after a newer\none was added. The newest secret can't be retired (`409` with detail\ncode `newest_secret`): rotate first. Retiring a retired secret changes\nnothing.\n",
        "tags": [
          "webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "description": "The retired secret.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSecret"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}/restore": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "operationId": "webhooks_restore",
        "summary": "Restore a webhook",
        "description": "Brings a deleted webhook back, with its settings and secrets, until\n`purge_after`. Deliveries that came due while it was deleted failed;\nattempt them again with `POST /v1/webhook-deliveries/{delivery_id}/retry`.\nRestoring counts against the plan's webhook limit (`402`).\n",
        "tags": [
          "webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "200": {
            "description": "The restored webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimitExceeded"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/webhooks/{webhook_id}/deliveries": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "operationId": "webhook_deliveries_list",
        "summary": "List deliveries",
        "description": "The webhook's deliveries, newest first. Kept for 30 days.\n",
        "tags": [
          "deliveries"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "filter",
            "in": "query",
            "style": "deepObject",
            "explode": true,
            "schema": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "status": {
                  "type": "string",
                  "enum": [
                    "pending",
                    "succeeded",
                    "failed"
                  ]
                }
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of deliveries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/webhook-deliveries/{delivery_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DeliveryId"
        }
      ],
      "get": {
        "operationId": "webhook_deliveries_get",
        "summary": "Get a delivery",
        "description": "The delivery with its payload and every attempt.\n",
        "tags": [
          "deliveries"
        ],
        "responses": {
          "200": {
            "description": "The delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryDetail"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/webhook-deliveries/{delivery_id}/retry": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DeliveryId"
        }
      ],
      "post": {
        "operationId": "webhook_deliveries_retry",
        "summary": "Retry a delivery",
        "description": "Attempts the delivery again now, whatever its status; the attempt runs\nin the background, and the delivery's `attempts` show it. `409` with\ndetail code `deleted` if the webhook was deleted.\n",
        "tags": [
          "deliveries"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/NoheadClient"
          }
        ],
        "responses": {
          "202": {
            "description": "The queued delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDelivery"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/projects/{project_id}/audit-events": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "get": {
        "operationId": "audit_events_list",
        "summary": "List a project's audit events",
        "description": "The project's audit events, newest first. API keys need the `audit:read`\nscope and see their own project only.\n",
        "tags": [
          "audit"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/AuditEventFilter"
          },
          {
            "$ref": "#/components/parameters/AuditEventSort"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of audit events.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditEventList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/health": {
      "get": {
        "operationId": "health_check",
        "summary": "Check API health",
        "description": "Returns the service status. Does not require authentication.",
        "tags": [
          "system"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The service is healthy.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                },
                "example": {
                  "status": "ok",
                  "version": "v1",
                  "time": "2026-09-27T12:00:00Z"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "operationId": "me_get",
        "summary": "Get the authenticated principal",
        "description": "The user or API key making the request. API key clients use it to\ndiscover their project and scopes.\n",
        "tags": [
          "system"
        ],
        "responses": {
          "200": {
            "description": "The authenticated principal.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Principal"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/feature-flags": {
      "get": {
        "operationId": "feature_flags_list",
        "summary": "Get evaluated feature flags",
        "description": "Feature flags evaluated for the caller. Without credentials,\nonly public flags are returned, evaluated without actors (for the\nmarketing website). With credentials, client flags are included,\nevaluated for the caller: an API key's project, or for the web app the\nuser and the given organization or project. Server flags are never\nreturned.\n",
        "tags": [
          "system"
        ],
        "security": [
          {},
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Evaluated flags.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeatureFlags"
                },
                "example": {
                  "object": "feature_flags",
                  "organization_id": "org_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
                  "project_id": null,
                  "flags": {
                    "new_editor": true
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "webhooks": {
    "event": {
      "post": {
        "operationId": "webhook_event",
        "summary": "A webhook event",
        "tags": [
          "webhooks"
        ],
        "description": "Sent to each subscribed webhook when something happens in a project.\nDelivery is at least once: the same event can arrive more than once, so\nprocess events idempotently, keyed by `webhook-id`. Respond with any\n2xx within 10 seconds; other responses and timeouts are retried 7\ntimes over about a day.\n\nRequests follow the Standard Webhooks specification\n(https://www.standardwebhooks.com), so its libraries verify them:\n`webhook-signature` is `v1,` followed by the base64 HMAC-SHA256 of\n`{webhook-id}.{webhook-timestamp}.{body}`, keyed with the base64-decoded\npart of the webhook's `whsec_` secret. For a day after the secret is\nrotated, the header holds a signature for each signing secret,\nspace-separated: accept the request when any of them verifies. Reject\nrequests whose timestamp is more than five minutes away from your clock.\n",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEventPayload"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received (any 2xx)."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Project-scoped API key, e.g. `nohead_sk_k7fz0a9c3m2q_<secret>`, or\n`nohead_pk_…` for a published-only key. Used by servers, CI, the CLI\nand coding agents.\n"
      }
    },
    "parameters": {
      "ProjectId": {
        "name": "project_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "prj_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
      },
      "CollectionRef": {
        "name": "collection_id",
        "in": "path",
        "required": true,
        "description": "Collection ID, or the collection slug when authenticating with an API key.",
        "schema": {
          "type": "string"
        },
        "example": "col_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
      },
      "FieldId": {
        "name": "field_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "fld_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
      },
      "MigrationId": {
        "name": "migration_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "examples": [
            "mig_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
          ]
        }
      },
      "AssetId": {
        "name": "asset_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "ast_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
      },
      "WebhookSecretId": {
        "name": "secret_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "whs_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
      },
      "WebhookId": {
        "name": "webhook_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "wh_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
      },
      "DeliveryId": {
        "name": "delivery_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "whd_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
      },
      "RecordId": {
        "name": "record_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "rec_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
      },
      "DraftId": {
        "name": "draft_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "drf_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
      },
      "RevisionId": {
        "name": "revision_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "example": "rev_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
      },
      "RevisionNumber": {
        "name": "revision",
        "in": "path",
        "required": true,
        "description": "Per-record revision number.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      },
      "RichText": {
        "name": "rich_text",
        "in": "query",
        "description": "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.",
        "schema": {
          "type": "string",
          "enum": [
            "document",
            "html",
            "markdown"
          ],
          "default": "document"
        }
      },
      "Expand": {
        "name": "expand",
        "in": "query",
        "description": "Comma-separated relation, asset or rich text field keys whose records or assets to embed under `expanded` (at most 5); for a rich text field, the assets its images show. Embedding needs permission to read what is embedded: `records:read` for relations, `assets:read` for assets and rich text (`403` otherwise).",
        "schema": {
          "type": "string"
        },
        "example": "author,tags"
      },
      "RecordFilter": {
        "name": "filter",
        "in": "query",
        "style": "deepObject",
        "explode": true,
        "description": "`filter[<key>]=value` (equal), or `filter[<key>][<operator>]=value`;\nfilters combine with AND. Keys are field keys, `published_at`,\n`deleted` (`true` lists soft-deleted records instead) and, in record\nlists and counts, `created_at` and `updated_at`.\n\n- `eq`, `ne`: equal, not equal. For fields with several values,\n  \"contains\" and \"does not contain\". `ne` matches records with no value.\n- `gt`, `gte`, `lt`, `lte`: integer, decimal and date fields with one\n  value, and the timestamps.\n- `in`: any of up to 100 comma-separated values (`\\,` is a comma\n  inside a value, `\\\\` a backslash); for fields with several values,\n  \"contains any of\".\n- `exists`: `true` for records with a value, `false` for those without\n  (and `published_at`: published or not).\n\nValues are parsed per field type (`\"5\"` is not the integer 5), but\nnot held to the field's limits or format (`price[lt]=10` works when\n`max` is 5; a slug filter that isn't a slug matches nothing). Dates\ntake `today`, and dates with a time `now` too. A day (`YYYY-MM-DD`)\ngiven for a date with a time, or a timestamp, covers that day in the\nfield's `time_zone` (UTC without one): `gte` from its start, `lte` to\nits end, `eq` within it. A date with a time matches the same moment\nwritten with any offset.\n",
        "schema": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/components/schemas/RecordFilterValue"
          }
        },
        "examples": {
          "upcoming": {
            "summary": "Events from today on",
            "value": {
              "starts_on": {
                "gte": "today"
              }
            }
          },
          "cheap": {
            "summary": "Published products under 50 in two categories",
            "value": {
              "published_at": {
                "exists": "true"
              },
              "price": {
                "lt": "50"
              },
              "category": {
                "in": "shoes,bags"
              }
            }
          }
        }
      },
      "AuditEventFilter": {
        "name": "filter",
        "in": "query",
        "style": "deepObject",
        "explode": true,
        "description": "`type` matches exactly, or by prefix with a trailing `.*`\n(`filter[type]=record.*`). `resource_type` takes one type, or several\nwith `[in]` (`filter[resource_type][in]=collection,field`). Unknown\nfilters are `400`.\n",
        "schema": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "type": {
              "type": "string",
              "examples": [
                "field.updated",
                "record.*"
              ]
            },
            "resource_type": {
              "oneOf": [
                {
                  "type": "string",
                  "examples": [
                    "record"
                  ]
                },
                {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "in"
                  ],
                  "properties": {
                    "in": {
                      "type": "string",
                      "description": "Comma-separated types."
                    }
                  }
                }
              ]
            },
            "resource_id": {
              "type": "string"
            },
            "actor_type": {
              "type": "string",
              "enum": [
                "user",
                "api_key",
                "system"
              ]
            },
            "actor_id": {
              "type": "string",
              "description": "A user (`usr_...`) or API key (`key_...`)."
            },
            "created_at": {
              "$ref": "#/components/schemas/TimeFilter"
            }
          }
        }
      },
      "RecordRevisionFilter": {
        "name": "filter",
        "in": "query",
        "style": "deepObject",
        "explode": true,
        "description": "Unknown filters are `400`.",
        "schema": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "operation": {
              "$ref": "#/components/schemas/RecordRevisionOperation"
            },
            "actor_id": {
              "type": "string",
              "description": "A user (`usr_...`) or API key (`key_...`)."
            },
            "created_at": {
              "$ref": "#/components/schemas/TimeFilter"
            }
          }
        }
      },
      "AuditEventSort": {
        "name": "sort",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "created_at",
            "-created_at"
          ],
          "default": "-created_at"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "Page size.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "description": "The `next_cursor` from the previous page.",
        "schema": {
          "type": "string"
        }
      },
      "DeletedFilter": {
        "name": "filter",
        "in": "query",
        "style": "deepObject",
        "explode": true,
        "description": "`filter[deleted]=true` lists soft-deleted items instead of active ones.",
        "schema": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "deleted": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        }
      },
      "AssetFilter": {
        "name": "filter",
        "in": "query",
        "style": "deepObject",
        "explode": true,
        "description": "`filter[deleted]=true` lists deleted assets instead.\n`filter[content_type]` lists only assets of a type: a MIME type or a\n`type/*` wildcard, or several with\n`filter[content_type][in]=image/*,application/pdf`, for example the\nones an asset field accepts (its `accepted_types`).\n`filter[kind]` lists only assets of a kind, or several with\n`filter[kind][in]=image,video`: `image`, `video` and `audio` by\ntheir types (`image/*` and so on); `document` for PDFs, plain text,\nMarkdown, CSV, and word processing, spreadsheet and presentation\nfiles (Microsoft Office, OpenDocument, RTF); `other` for every other\nfile.\n",
        "schema": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "deleted": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "kind": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/AssetKind"
                },
                {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "in"
                  ],
                  "properties": {
                    "in": {
                      "type": "string",
                      "description": "Comma-separated kinds.",
                      "examples": [
                        "image,video"
                      ]
                    }
                  }
                }
              ]
            },
            "content_type": {
              "anyOf": [
                {
                  "type": "string",
                  "examples": [
                    "image/*"
                  ]
                },
                {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "in"
                  ],
                  "properties": {
                    "in": {
                      "type": "string",
                      "description": "Up to 50 comma-separated MIME types or `type/*` wildcards.",
                      "examples": [
                        "image/*,application/pdf"
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "IfMatch": {
        "name": "If-Match",
        "in": "header",
        "description": "The revision you last read (the record's, or the draft's for a draft), e.g. `\"7\"`. Stale writes fail with 412.",
        "schema": {
          "type": "string"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "A unique value (1-255 printable ASCII characters) that makes retrying\nthis request safe. The first response (below 500) is stored for 24\nhours per user or API key; retries with the same key and the same\nrequest get it again with an `Idempotent-Replayed: true` header. The\nsame key with a different request is refused with `400`; a retry while\nthe first request is still running gets `409`.\n",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "example": "8f14e45f-ceea-467a-9575-0f1a3f2c1d2e"
      },
      "NoheadClient": {
        "name": "Nohead-Client",
        "in": "header",
        "description": "First-party client identifier recorded in history (e.g. `cli/0.3.1`). Informational only.",
        "schema": {
          "type": "string"
        }
      },
      "ChangeNote": {
        "name": "Nohead-Change-Note",
        "in": "header",
        "description": "Optional reason for the change, kept with the record revision, schema\nchange or field migration it makes (at most 500 characters once\ndecoded). Percent-encoded UTF-8, as\n`encodeURIComponent` encodes it, so any language fits in a header:\n`Rettet%20stavefejl%20p%C3%A5%20forsiden`. Plain ASCII may be sent\nas is. Other bytes are `400`.\n",
        "schema": {
          "type": "string"
        }
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "Requests allowed in the current window. Sent on every authenticated response.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitRemaining": {
        "description": "Requests left in the current window.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitReset": {
        "description": "Seconds until the window resets.",
        "schema": {
          "type": "integer"
        }
      },
      "RequestId": {
        "description": "Unique identifier for the request, also echoed in error bodies.",
        "schema": {
          "$ref": "#/components/schemas/RequestId"
        }
      },
      "ETag": {
        "description": "The current revision (the record's, or the draft's), e.g. `\"7\"`. Send it back as `If-Match`.",
        "schema": {
          "type": "string"
        }
      },
      "UsageWarning": {
        "description": "Set when the organization is over a soft plan limit, as\n`<metric>=<usage>/<limit>` (e.g. `api_requests=100234/100000`). Requests\nstill succeed. Any API-key request may carry it for `api_requests`.\n",
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "RequestId": {
        "type": "string",
        "pattern": "^req_[A-Za-z0-9]+$",
        "examples": [
          "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
        ]
      },
      "Timestamp": {
        "type": "string",
        "format": "date-time",
        "description": "ISO 8601 timestamp in UTC.",
        "examples": [
          "2026-09-27T12:00:00.000Z"
        ]
      },
      "NullableTimestamp": {
        "type": [
          "string",
          "null"
        ],
        "format": "date-time"
      },
      "Health": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "version",
          "time"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ]
          },
          "version": {
            "type": "string",
            "description": "Nohead API version.",
            "examples": [
              "v1"
            ]
          },
          "time": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "ListMeta": {
        "type": "object",
        "description": "Cursor pagination metadata returned with every list.",
        "additionalProperties": false,
        "required": [
          "next_cursor",
          "has_more"
        ],
        "properties": {
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Opaque cursor for the next page, or null on the last page."
          },
          "has_more": {
            "type": "boolean"
          }
        }
      },
      "RecordFilterValue": {
        "description": "A value to equal, or operators with their values (see the `filter` parameter).",
        "oneOf": [
          {
            "type": "string"
          },
          {
            "type": "object",
            "additionalProperties": false,
            "minProperties": 1,
            "properties": {
              "eq": {
                "type": "string"
              },
              "ne": {
                "type": "string"
              },
              "gt": {
                "type": "string"
              },
              "gte": {
                "type": "string"
              },
              "lt": {
                "type": "string"
              },
              "lte": {
                "type": "string"
              },
              "in": {
                "type": "string",
                "description": "Comma-separated; `\\,` is a comma inside a value."
              },
              "exists": {
                "type": "string",
                "enum": [
                  "true",
                  "false"
                ]
              }
            }
          }
        ]
      },
      "FieldType": {
        "type": "string",
        "enum": [
          "text",
          "long_text",
          "rich_text",
          "integer",
          "decimal",
          "date",
          "boolean",
          "enum",
          "asset",
          "relation",
          "json"
        ]
      },
      "Field": {
        "description": "A field, typed by its `type`, which also decides the options its `configuration` takes.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/TextField"
          },
          {
            "$ref": "#/components/schemas/LongTextField"
          },
          {
            "$ref": "#/components/schemas/RichTextField"
          },
          {
            "$ref": "#/components/schemas/IntegerField"
          },
          {
            "$ref": "#/components/schemas/DecimalField"
          },
          {
            "$ref": "#/components/schemas/DateField"
          },
          {
            "$ref": "#/components/schemas/BooleanField"
          },
          {
            "$ref": "#/components/schemas/EnumField"
          },
          {
            "$ref": "#/components/schemas/AssetField"
          },
          {
            "$ref": "#/components/schemas/RelationField"
          },
          {
            "$ref": "#/components/schemas/JsonField"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "text": "#/components/schemas/TextField",
            "long_text": "#/components/schemas/LongTextField",
            "rich_text": "#/components/schemas/RichTextField",
            "integer": "#/components/schemas/IntegerField",
            "decimal": "#/components/schemas/DecimalField",
            "date": "#/components/schemas/DateField",
            "boolean": "#/components/schemas/BooleanField",
            "enum": "#/components/schemas/EnumField",
            "asset": "#/components/schemas/AssetField",
            "relation": "#/components/schemas/RelationField",
            "json": "#/components/schemas/JsonField"
          }
        }
      },
      "TextField": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "text"
              },
              "configuration": {
                "$ref": "#/components/schemas/TextFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "LongTextField": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "long_text"
              },
              "configuration": {
                "$ref": "#/components/schemas/LongTextFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "RichTextField": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "rich_text"
              },
              "configuration": {
                "$ref": "#/components/schemas/RichTextFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "IntegerField": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "integer"
              },
              "configuration": {
                "$ref": "#/components/schemas/IntegerFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "DecimalField": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "decimal"
              },
              "configuration": {
                "$ref": "#/components/schemas/DecimalFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "DateField": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "date"
              },
              "configuration": {
                "$ref": "#/components/schemas/DateFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "BooleanField": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "boolean"
              },
              "configuration": {
                "$ref": "#/components/schemas/BooleanFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "EnumField": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "enum"
              },
              "configuration": {
                "$ref": "#/components/schemas/EnumFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "AssetField": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "asset"
              },
              "configuration": {
                "$ref": "#/components/schemas/AssetFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "RelationField": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "relation"
              },
              "configuration": {
                "$ref": "#/components/schemas/RelationFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "JsonField": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "json"
              },
              "configuration": {
                "$ref": "#/components/schemas/JsonFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "FieldProperties": {
        "type": "object",
        "description": "What every field has; `Field` adds its `type` and that type's `configuration`.",
        "required": [
          "id",
          "object",
          "collection_id",
          "name",
          "key",
          "required",
          "multiple",
          "position",
          "deleted_at",
          "purge_after",
          "aliases",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable field ID. Never changes, even when the field is renamed.",
            "examples": [
              "fld_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "field"
          },
          "collection_id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "Display name. Safe to change."
          },
          "key": {
            "type": "string",
            "description": "Key used in record data. Part of the API contract."
          },
          "required": {
            "type": "boolean",
            "description": "Every record must have a value. Not available for boolean fields (a boolean is true or false; no value reads as false)."
          },
          "multiple": {
            "type": "boolean",
            "description": "A list of distinct values (a repeated value is refused with `duplicate_value`, an empty string with `blank_value`). Not available for boolean, long_text, rich_text and json fields."
          },
          "position": {
            "type": "integer",
            "description": "Where the field sorts in the collection's order, lowest first. New fields are added last; `PUT /v1/collections/{collection_id}/field-order` changes the order, numbering the fields from 0."
          },
          "deleted_at": {
            "description": "When the field was deleted; null unless it is. Its values stay hidden in records until it is restored or purged.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "purge_after": {
            "description": "When a deleted field and its values are removed for good, unless restored first.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "aliases": {
            "type": "array",
            "description": "Old keys of a renamed field that still work until `expires_at`:\nrecord data also carries the value under them, and writes, filters,\nsorts and `expand` accept them. Responses about the collection then\nhave `Deprecation` and `Sunset` headers.\n",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "key",
                "expires_at"
              ],
              "properties": {
                "key": {
                  "type": "string"
                },
                "expires_at": {
                  "$ref": "#/components/schemas/Timestamp"
                }
              }
            }
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "TextFieldConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "description": "Plain text up to 10,000 characters, or a `format`.",
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Help text for editors."
          },
          "searchable": {
            "type": "boolean",
            "description": "Search words match the field, in every search (API keys, search tokens, members). Default true for text, long_text, rich_text and enum."
          },
          "filterable": {
            "type": "boolean",
            "description": "API searches can filter on it. Default false."
          },
          "sortable": {
            "type": "boolean",
            "description": "API searches can sort on it (one value only). Default false."
          },
          "min_length": {
            "type": "integer",
            "minimum": 0
          },
          "max_length": {
            "type": "integer",
            "minimum": 0
          },
          "format": {
            "type": "string",
            "enum": [
              "slug",
              "url",
              "email"
            ],
            "description": "`slug` (always unique, one value), `url` (absolute http or https) or `email`; each sets its own length limits."
          },
          "unique": {
            "type": "boolean",
            "description": "No two active records of the collection share a value (one value only; a slug is always unique)."
          }
        }
      },
      "LongTextFieldConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "description": "Text up to 100,000 characters.",
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Help text for editors."
          },
          "searchable": {
            "type": "boolean",
            "description": "Search words match the field, in every search (API keys, search tokens, members). Default true for text, long_text, rich_text and enum."
          },
          "filterable": {
            "type": "boolean",
            "description": "API searches can filter on it. Default false."
          },
          "sortable": {
            "type": "boolean",
            "description": "API searches can sort on it (one value only). Default false."
          },
          "min_length": {
            "type": "integer",
            "minimum": 0
          },
          "max_length": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "RichTextFieldConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "description": "A rich text document up to 1,000,000 bytes (`too_large`), written as Markdown or a document (see `RecordData`).",
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Help text for editors."
          },
          "searchable": {
            "type": "boolean",
            "description": "Search words match the field, in every search (API keys, search tokens, members). Default true for text, long_text, rich_text and enum."
          },
          "filterable": {
            "type": "boolean",
            "description": "API searches can filter on it. Default false."
          },
          "sortable": {
            "type": "boolean",
            "description": "API searches can sort on it (one value only). Default false."
          }
        }
      },
      "IntegerFieldConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Help text for editors."
          },
          "searchable": {
            "type": "boolean",
            "description": "Search words match the field, in every search (API keys, search tokens, members). Default true for text, long_text, rich_text and enum."
          },
          "filterable": {
            "type": "boolean",
            "description": "API searches can filter on it. Default false."
          },
          "sortable": {
            "type": "boolean",
            "description": "API searches can sort on it (one value only). Default false."
          },
          "min": {
            "type": "integer"
          },
          "max": {
            "type": "integer"
          },
          "unique": {
            "type": "boolean",
            "description": "No two active records of the collection share a value (one value only)."
          }
        }
      },
      "DecimalFieldConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Help text for editors."
          },
          "searchable": {
            "type": "boolean",
            "description": "Search words match the field, in every search (API keys, search tokens, members). Default true for text, long_text, rich_text and enum."
          },
          "filterable": {
            "type": "boolean",
            "description": "API searches can filter on it. Default false."
          },
          "sortable": {
            "type": "boolean",
            "description": "API searches can sort on it (one value only). Default false."
          },
          "min": {
            "type": "number"
          },
          "max": {
            "type": "number"
          }
        }
      },
      "DateFieldConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Help text for editors."
          },
          "searchable": {
            "type": "boolean",
            "description": "Search words match the field, in every search (API keys, search tokens, members). Default true for text, long_text, rich_text and enum."
          },
          "filterable": {
            "type": "boolean",
            "description": "API searches can filter on it. Default false."
          },
          "sortable": {
            "type": "boolean",
            "description": "API searches can sort on it (one value only). Default false."
          },
          "include_time": {
            "type": "boolean",
            "description": "Holds a moment (ISO 8601 with an offset) instead of a calendar date; changing it is a field migration."
          },
          "time_zone": {
            "type": "string",
            "description": "An IANA time zone (`Europe/Copenhagen`) moments are returned in; changing it never rewrites values."
          }
        }
      },
      "BooleanFieldConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Help text for editors."
          },
          "searchable": {
            "type": "boolean",
            "description": "Search words match the field, in every search (API keys, search tokens, members). Default true for text, long_text, rich_text and enum."
          },
          "filterable": {
            "type": "boolean",
            "description": "API searches can filter on it. Default false."
          },
          "sortable": {
            "type": "boolean",
            "description": "API searches can sort on it (one value only). Default false."
          }
        }
      },
      "EnumFieldConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "options"
        ],
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Help text for editors."
          },
          "searchable": {
            "type": "boolean",
            "description": "Search words match the field, in every search (API keys, search tokens, members). Default true for text, long_text, rich_text and enum."
          },
          "filterable": {
            "type": "boolean",
            "description": "API searches can filter on it. Default false."
          },
          "sortable": {
            "type": "boolean",
            "description": "API searches can sort on it (one value only). Default false."
          },
          "options": {
            "type": "array",
            "minItems": 1,
            "maxItems": 500,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          }
        }
      },
      "AssetFieldConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Help text for editors."
          },
          "searchable": {
            "type": "boolean",
            "description": "Search words match the field, in every search (API keys, search tokens, members). Default true for text, long_text, rich_text and enum."
          },
          "filterable": {
            "type": "boolean",
            "description": "API searches can filter on it. Default false."
          },
          "sortable": {
            "type": "boolean",
            "description": "API searches can sort on it (one value only). Default false."
          },
          "accepted_types": {
            "type": "array",
            "maxItems": 50,
            "description": "MIME types or `type/*` wildcards newly written values must have (`[\"image/*\", \"application/pdf\"]`); any file when absent.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "RelationFieldConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "target_collection_id"
        ],
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Help text for editors."
          },
          "searchable": {
            "type": "boolean",
            "description": "Search words match the field, in every search (API keys, search tokens, members). Default true for text, long_text, rich_text and enum."
          },
          "filterable": {
            "type": "boolean",
            "description": "API searches can filter on it. Default false."
          },
          "sortable": {
            "type": "boolean",
            "description": "API searches can sort on it (one value only). Default false."
          },
          "target_collection_id": {
            "type": "string",
            "description": "The collection (same project) whose records it points at."
          }
        }
      },
      "JsonFieldConfiguration": {
        "type": "object",
        "additionalProperties": false,
        "description": "Any JSON value up to 100,000 bytes (`too_large`), nested at most 32 levels deep (`too_deep`): for data with a shape of its own, such as settings or another service's payload. Content belongs in typed fields, and large data in an asset.",
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Help text for editors."
          },
          "searchable": {
            "type": "boolean",
            "description": "Search words match the field, in every search (API keys, search tokens, members). Default true for text, long_text, rich_text and enum."
          },
          "filterable": {
            "type": "boolean",
            "description": "API searches can filter on it. Default false."
          },
          "sortable": {
            "type": "boolean",
            "description": "API searches can sort on it (one value only). Default false."
          }
        }
      },
      "FieldConfiguration": {
        "description": "Type-specific options, e.g. `max_length`, `options`, `target_collection_id`,\n`accepted_types` (asset fields: MIME types or `type/*` wildcards that newly\nwritten values must have; any file when absent), `include_time` and\n`time_zone` (date fields, below), `format` (text fields, below),\n`unique` (text and integer fields, below), plus\nthe options for searches with API keys: `searchable` (the search words match the\nfield; default true for text, long_text, rich_text and enum), `filterable` and\n`sortable` (default false).\n\nDate fields hold a calendar date, `YYYY-MM-DD`, with no time and no\ntime zone: returned exactly as written, so it never shows as the day\nbefore or after. With `include_time: true` they hold a moment: ISO\n8601 with an offset, stored in UTC and returned in UTC, or with the\noffset of `time_zone` (an IANA name such as `Europe/Copenhagen`,\ndaylight saving included) when the field has one. Input may use any\noffset. Changing `time_zone` never rewrites values; turning\n`include_time` on or off does, through a field migration.\n\nText fields (not long text) can have a `format`: `slug`\n(lowercase letters, digits and single hyphens, at most 200\ncharacters; one value per record, never a list, and always\nunique: a slug field has `unique: true`), `url` (an absolute\n`http` or `https` address) or `email`. A value that doesn't match is\nrefused with `invalid_format`. A format sets its own length limits\n(254 characters for emails, 2,048 for URLs), so `min_length` and\n`max_length` are for plain text. Text and integer\nfields with one value can be `unique`: no two active records of the\ncollection share a value (emails compare ignoring capitals; records\nwithout a value don't count). A taken value is refused with\n`taken` and the `record_id` that has it. Turning `unique` on is\nrefused with `duplicate_values` while records share a value (and\nso is restoring a deleted unique field, `409`). A field migration\nto a unique field is refused with `duplicate_values` when its\nconverted values or backfill would be shared, and fails if values\nwritten while it waits would be.\n",
        "anyOf": [
          {
            "$ref": "#/components/schemas/TextFieldConfiguration"
          },
          {
            "$ref": "#/components/schemas/LongTextFieldConfiguration"
          },
          {
            "$ref": "#/components/schemas/RichTextFieldConfiguration"
          },
          {
            "$ref": "#/components/schemas/IntegerFieldConfiguration"
          },
          {
            "$ref": "#/components/schemas/DecimalFieldConfiguration"
          },
          {
            "$ref": "#/components/schemas/DateFieldConfiguration"
          },
          {
            "$ref": "#/components/schemas/BooleanFieldConfiguration"
          },
          {
            "$ref": "#/components/schemas/EnumFieldConfiguration"
          },
          {
            "$ref": "#/components/schemas/AssetFieldConfiguration"
          },
          {
            "$ref": "#/components/schemas/RelationFieldConfiguration"
          },
          {
            "$ref": "#/components/schemas/JsonFieldConfiguration"
          }
        ]
      },
      "RecordCount": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "collection_id",
          "count"
        ],
        "properties": {
          "object": {
            "const": "record_count"
          },
          "collection_id": {
            "type": "string"
          },
          "count": {
            "type": "integer"
          }
        }
      },
      "FieldCreate": {
        "description": "A new field. Its `type` decides the options `configuration` takes.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/TextFieldCreate"
          },
          {
            "$ref": "#/components/schemas/LongTextFieldCreate"
          },
          {
            "$ref": "#/components/schemas/RichTextFieldCreate"
          },
          {
            "$ref": "#/components/schemas/IntegerFieldCreate"
          },
          {
            "$ref": "#/components/schemas/DecimalFieldCreate"
          },
          {
            "$ref": "#/components/schemas/DateFieldCreate"
          },
          {
            "$ref": "#/components/schemas/BooleanFieldCreate"
          },
          {
            "$ref": "#/components/schemas/EnumFieldCreate"
          },
          {
            "$ref": "#/components/schemas/AssetFieldCreate"
          },
          {
            "$ref": "#/components/schemas/RelationFieldCreate"
          },
          {
            "$ref": "#/components/schemas/JsonFieldCreate"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "text": "#/components/schemas/TextFieldCreate",
            "long_text": "#/components/schemas/LongTextFieldCreate",
            "rich_text": "#/components/schemas/RichTextFieldCreate",
            "integer": "#/components/schemas/IntegerFieldCreate",
            "decimal": "#/components/schemas/DecimalFieldCreate",
            "date": "#/components/schemas/DateFieldCreate",
            "boolean": "#/components/schemas/BooleanFieldCreate",
            "enum": "#/components/schemas/EnumFieldCreate",
            "asset": "#/components/schemas/AssetFieldCreate",
            "relation": "#/components/schemas/RelationFieldCreate",
            "json": "#/components/schemas/JsonFieldCreate"
          }
        }
      },
      "TextFieldCreate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldCreateProperties"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "text"
              },
              "configuration": {
                "$ref": "#/components/schemas/TextFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "LongTextFieldCreate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldCreateProperties"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "long_text"
              },
              "configuration": {
                "$ref": "#/components/schemas/LongTextFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "RichTextFieldCreate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldCreateProperties"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "rich_text"
              },
              "configuration": {
                "$ref": "#/components/schemas/RichTextFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "IntegerFieldCreate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldCreateProperties"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "integer"
              },
              "configuration": {
                "$ref": "#/components/schemas/IntegerFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "DecimalFieldCreate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldCreateProperties"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "decimal"
              },
              "configuration": {
                "$ref": "#/components/schemas/DecimalFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "DateFieldCreate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldCreateProperties"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "date"
              },
              "configuration": {
                "$ref": "#/components/schemas/DateFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "BooleanFieldCreate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldCreateProperties"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "boolean"
              },
              "configuration": {
                "$ref": "#/components/schemas/BooleanFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "EnumFieldCreate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldCreateProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "enum"
              },
              "configuration": {
                "$ref": "#/components/schemas/EnumFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "AssetFieldCreate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldCreateProperties"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "asset"
              },
              "configuration": {
                "$ref": "#/components/schemas/AssetFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "RelationFieldCreate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldCreateProperties"
          },
          {
            "type": "object",
            "required": [
              "type",
              "configuration"
            ],
            "properties": {
              "type": {
                "const": "relation"
              },
              "configuration": {
                "$ref": "#/components/schemas/RelationFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "JsonFieldCreate": {
        "allOf": [
          {
            "$ref": "#/components/schemas/FieldCreateProperties"
          },
          {
            "type": "object",
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "json"
              },
              "configuration": {
                "$ref": "#/components/schemas/JsonFieldConfiguration"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "FieldCreateProperties": {
        "type": "object",
        "description": "What every new field takes; `FieldCreate` adds its `type` and that type's `configuration`.",
        "required": [
          "name",
          "key"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "key": {
            "type": "string",
            "description": "The field's key in records' `data`, filters and sorts. Reserved for records' own attributes, and a few kept for later: `id`, `object`, `collection`, `data`, `status`, `published_at`, `created_at`, `updated_at`, `deleted`, `deleted_at`, `purge_after`, `revision` and `schema_version`."
          },
          "required": {
            "type": "boolean",
            "description": "Every record must have a value. Not available for boolean fields (a boolean is true or false; no value reads as false)."
          },
          "multiple": {
            "type": "boolean",
            "description": "A list of distinct values (a repeated value is refused with `duplicate_value`, an empty string with `blank_value`). Not available for boolean, long_text, rich_text and json fields."
          }
        }
      },
      "FieldUpdate": {
        "type": "object",
        "description": "Renames, describes or loosens a field. A change to its `type` or `multiple` rewrites record values, so it is a field migration (`POST /v1/collections/{collection_id}/migrations`); either key here is `400` `unknown_parameter`, saying so.",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "key": {
            "type": "string",
            "description": "The field's key in records' `data`, filters and sorts. Reserved for records' own attributes, and a few kept for later: `id`, `object`, `collection`, `data`, `status`, `published_at`, `created_at`, `updated_at`, `deleted`, `deleted_at`, `purge_after`, `revision` and `schema_version`."
          },
          "required": {
            "type": "boolean",
            "description": "Every record must have a value. Not available for boolean fields (a boolean is true or false; no value reads as false)."
          },
          "configuration": {
            "$ref": "#/components/schemas/FieldConfiguration"
          }
        }
      },
      "FieldList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "Collection": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "object",
          "project_id",
          "name",
          "slug",
          "description",
          "schema_version",
          "deleted_at",
          "purge_after",
          "public_search",
          "fields",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "col_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "collection"
          },
          "project_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "schema_version": {
            "type": "integer"
          },
          "deleted_at": {
            "description": "When the collection was deleted; null unless it is.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "purge_after": {
            "description": "When a deleted collection is removed for good, with its fields and records, unless restored first.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "public_search": {
            "type": "boolean",
            "description": "Whether the project's search tokens (made in the web app) find\nits published records, from a browser or a backend. Off by\ndefault: every field of those records becomes readable by anyone\nwith a token, so turn it on only for collections whose published\nrecords are public. A change reaches search tokens within\nseconds.\n"
          },
          "fields": {
            "type": "array",
            "description": "Active fields in position order.",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "CollectionCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "slug"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "public_search": {
            "type": "boolean",
            "default": false
          },
          "fields": {
            "type": "array",
            "description": "At most 100 (`too_many`).",
            "items": {
              "$ref": "#/components/schemas/FieldCreate"
            }
          }
        }
      },
      "CollectionUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "public_search": {
            "type": "boolean"
          }
        }
      },
      "CollectionList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Collection"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "SchemaDefinition": {
        "type": "object",
        "description": "The complete collection definition at one schema version.",
        "additionalProperties": false,
        "required": [
          "id",
          "name",
          "slug",
          "description",
          "deleted_at",
          "fields"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "deleted_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "public_search": {
            "type": "boolean",
            "description": "Absent from schemas before the setting existed (off)."
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "name",
                "key",
                "type",
                "required",
                "multiple",
                "position",
                "configuration",
                "deleted_at"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "key": {
                  "type": "string"
                },
                "type": {
                  "$ref": "#/components/schemas/FieldType"
                },
                "required": {
                  "type": "boolean"
                },
                "multiple": {
                  "type": "boolean"
                },
                "position": {
                  "type": "integer"
                },
                "configuration": {
                  "$ref": "#/components/schemas/FieldConfiguration"
                },
                "deleted_at": {
                  "$ref": "#/components/schemas/NullableTimestamp"
                }
              }
            }
          }
        }
      },
      "Schema": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "collection_id",
          "version",
          "definition"
        ],
        "properties": {
          "object": {
            "const": "schema"
          },
          "collection_id": {
            "type": "string"
          },
          "version": {
            "type": "integer"
          },
          "definition": {
            "$ref": "#/components/schemas/SchemaDefinition"
          }
        }
      },
      "Actor": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "id",
          "name"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "user",
              "api_key",
              "system"
            ]
          },
          "id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The user (`usr_...`) or API key (`key_...`), or null for system changes."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Resolved when read, never stored: a user's current name (or\nemail), \"Deleted user\" once they deleted their account, an API\nkey's name, or \"System\".\n"
          }
        }
      },
      "SchemaChange": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SchemaChangeProperties"
          }
        ],
        "unevaluatedProperties": false
      },
      "SchemaChangeProperties": {
        "type": "object",
        "required": [
          "id",
          "object",
          "collection_id",
          "from_version",
          "to_version",
          "operation",
          "payload",
          "actor",
          "via",
          "note",
          "request_id",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "sch_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "schema_change"
          },
          "collection_id": {
            "type": "string"
          },
          "from_version": {
            "type": "integer"
          },
          "to_version": {
            "type": "integer"
          },
          "operation": {
            "type": "string",
            "enum": [
              "create_collection",
              "update_collection",
              "delete_collection",
              "restore_collection",
              "add_field",
              "update_field",
              "delete_field",
              "restore_field",
              "migrate_field",
              "reorder_fields"
            ]
          },
          "payload": {
            "type": "object",
            "description": "Operation details, e.g. `changes` and `breaking` for updates."
          },
          "actor": {
            "$ref": "#/components/schemas/Actor"
          },
          "via": {
            "$ref": "#/components/schemas/Via"
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "request_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "SchemaChangeDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SchemaChangeProperties"
          },
          {
            "type": "object",
            "required": [
              "before",
              "after"
            ],
            "properties": {
              "before": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/SchemaDefinition"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "after": {
                "$ref": "#/components/schemas/SchemaDefinition"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "SchemaChangeList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SchemaChange"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "FieldDefinition": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "configuration",
          "multiple",
          "required"
        ],
        "properties": {
          "type": {
            "$ref": "#/components/schemas/FieldType"
          },
          "configuration": {
            "$ref": "#/components/schemas/FieldConfiguration"
          },
          "multiple": {
            "type": "boolean",
            "description": "A list of distinct values (a repeated value is refused with `duplicate_value`, an empty string with `blank_value`). Not available for boolean, long_text, rich_text and json fields."
          },
          "required": {
            "type": "boolean"
          }
        }
      },
      "FieldMigrationRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "field_id"
        ],
        "description": "The field, and the parts of its definition to change; omitted parts stay as they are.",
        "properties": {
          "field_id": {
            "type": "string",
            "description": "One of the collection's fields (`422` otherwise).",
            "examples": [
              "fld_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "type": {
            "$ref": "#/components/schemas/FieldType"
          },
          "configuration": {
            "description": "The complete new configuration. When the type changes and this is omitted, only `description`, `searchable`, `filterable` and `sortable` carry over.",
            "$ref": "#/components/schemas/FieldConfiguration"
          },
          "multiple": {
            "type": "boolean",
            "description": "A list of distinct values (a repeated value is refused with `duplicate_value`, an empty string with `blank_value`). Not available for boolean, long_text, rich_text and json fields."
          },
          "required": {
            "type": "boolean"
          },
          "backfill": {
            "description": "Value for active records that have no value, validated like a record value of the new definition; an empty string is refused with `blank_value`."
          },
          "on_invalid": {
            "type": "string",
            "enum": [
              "fail",
              "clear"
            ],
            "default": "fail",
            "description": "`clear` removes values that cannot be converted (or backfills them); `fail` refuses the migration."
          },
          "time_zone": {
            "type": "string",
            "description": "When a date field's `include_time` is turned off: the IANA time zone\n(e.g. `Europe/Copenhagen`) whose day each moment falls on. Default:\nthe field's `time_zone`, else UTC. Refused for any other change.\n",
            "examples": [
              "Europe/Copenhagen"
            ]
          }
        }
      },
      "FieldMigrationCounts": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "total",
          "unchanged",
          "converted",
          "backfilled",
          "cleared",
          "invalid"
        ],
        "description": "Records by outcome, including soft-deleted records (which are converted but never backfilled).",
        "properties": {
          "total": {
            "type": "integer"
          },
          "unchanged": {
            "type": "integer"
          },
          "converted": {
            "type": "integer"
          },
          "backfilled": {
            "type": "integer"
          },
          "cleared": {
            "type": "integer"
          },
          "invalid": {
            "type": "integer"
          }
        }
      },
      "FieldMigrationPreview": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "field_id",
          "from",
          "to",
          "conversion",
          "records",
          "samples"
        ],
        "properties": {
          "object": {
            "const": "field_migration_preview"
          },
          "field_id": {
            "type": "string"
          },
          "from": {
            "$ref": "#/components/schemas/FieldDefinition"
          },
          "to": {
            "$ref": "#/components/schemas/FieldDefinition"
          },
          "conversion": {
            "type": "string",
            "enum": [
              "safe",
              "convertible",
              "conditional"
            ],
            "description": "`safe`: every value converts unchanged in meaning. `convertible`: every value converts, the representation changes. `conditional`: some values may not convert."
          },
          "records": {
            "$ref": "#/components/schemas/FieldMigrationCounts"
          },
          "samples": {
            "type": "array",
            "description": "Up to 10 affected records, invalid ones first.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "record_id",
                "deleted_at",
                "outcome",
                "before",
                "after",
                "error"
              ],
              "properties": {
                "record_id": {
                  "type": "string"
                },
                "deleted_at": {
                  "$ref": "#/components/schemas/NullableTimestamp"
                },
                "outcome": {
                  "type": "string",
                  "enum": [
                    "converted",
                    "backfilled",
                    "cleared",
                    "invalid"
                  ]
                },
                "before": {
                  "description": "The stored value before the migration, or null."
                },
                "after": {
                  "description": "The value after the migration, or null when cleared or invalid."
                },
                "error": {
                  "oneOf": [
                    {
                      "type": "null"
                    },
                    {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "FieldMigration": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "object",
          "collection_id",
          "field_id",
          "status",
          "from",
          "to",
          "backfill",
          "on_invalid",
          "time_zone",
          "records",
          "failure",
          "schema_change_id",
          "cancel_requested_at",
          "actor",
          "via",
          "note",
          "request_id",
          "created_at",
          "started_at",
          "completed_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "mig_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "field_migration"
          },
          "collection_id": {
            "type": "string"
          },
          "field_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "complete",
              "failed",
              "cancelled"
            ]
          },
          "from": {
            "$ref": "#/components/schemas/FieldDefinition"
          },
          "to": {
            "$ref": "#/components/schemas/FieldDefinition"
          },
          "backfill": {
            "description": "`{\"value\": ...}` when missing values are filled in, otherwise null.",
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "required": [
                  "value"
                ],
                "properties": {
                  "value": {}
                }
              }
            ]
          },
          "on_invalid": {
            "type": "string",
            "enum": [
              "fail",
              "clear"
            ]
          },
          "time_zone": {
            "type": [
              "string",
              "null"
            ],
            "description": "The time zone dates were read in when `include_time` was turned off, if one was given."
          },
          "records": {
            "$ref": "#/components/schemas/FieldMigrationCounts"
          },
          "failure": {
            "description": "Why the migration failed; null otherwise. A failed migration changed nothing.",
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "required": [
                  "message"
                ],
                "properties": {
                  "message": {
                    "type": "string"
                  }
                }
              }
            ]
          },
          "schema_change_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The `migrate_field` schema change, once complete."
          },
          "cancel_requested_at": {
            "description": "When cancelling was asked for, while a running migration rolls back.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "actor": {
            "$ref": "#/components/schemas/Actor"
          },
          "via": {
            "$ref": "#/components/schemas/Via"
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "request_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "started_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "completed_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          }
        }
      },
      "FieldMigrationList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FieldMigration"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "RecordSchedule": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "record_id",
          "publish_at",
          "unpublish_at",
          "last_error"
        ],
        "description": "When the record publishes or unpublishes on its own (within a minute of\nthe time), set with `PUT /v1/records/{record_id}/schedule`. A time is\ncleared once it has run, or once the record is published or\nunpublished by hand or deleted. `last_error` explains the last\nscheduled change that could not be made, until a new schedule is set\nor a scheduled change is made.\n",
        "properties": {
          "object": {
            "const": "schedule"
          },
          "record_id": {
            "type": "string"
          },
          "publish_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "unpublish_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "RecordScheduleUpdate": {
        "type": "object",
        "additionalProperties": false,
        "description": "The whole schedule. A time in the future, or null for none; a time left out is none too.",
        "properties": {
          "publish_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "unpublish_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          }
        }
      },
      "RecordPublication": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "record_id",
          "published_at",
          "revision",
          "published_by"
        ],
        "description": "A published record's live state.",
        "properties": {
          "object": {
            "const": "publication"
          },
          "record_id": {
            "type": "string"
          },
          "published_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "revision": {
            "type": "integer",
            "description": "The revision that is live, the record's current one (a live record's edits are live; a draft keeps changes back)."
          },
          "published_by": {
            "description": "Who published it last; null when that revision is no longer kept.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/Actor"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "ScheduledChange": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "action",
          "at",
          "record_id",
          "draft_id"
        ],
        "properties": {
          "object": {
            "const": "scheduled_change"
          },
          "action": {
            "type": "string",
            "description": "`publish` and `unpublish` are the record's schedule; `merge` is a draft's.",
            "enum": [
              "publish",
              "unpublish",
              "merge"
            ]
          },
          "at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "record_id": {
            "type": "string"
          },
          "draft_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The draft that merges, for `merge`."
          }
        }
      },
      "ScheduledChangeList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScheduledChange"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "RecordRevisionOperation": {
        "type": "string",
        "description": "What made the revision; `merge` is a draft's changes.",
        "enum": [
          "create",
          "update",
          "publish",
          "unpublish",
          "delete",
          "restore",
          "revert",
          "migrate",
          "merge"
        ]
      },
      "TimeFilter": {
        "type": "object",
        "additionalProperties": false,
        "description": "A time range, as record lists filter times (`filter[created_at][gte]=2026-10-01T00:00:00Z`).",
        "properties": {
          "gte": {
            "type": "string",
            "format": "date-time"
          },
          "gt": {
            "type": "string",
            "format": "date-time"
          },
          "lte": {
            "type": "string",
            "format": "date-time"
          },
          "lt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Via": {
        "type": "string",
        "description": "The client a change came through; `scheduler` for scheduled changes.",
        "enum": [
          "ui",
          "api",
          "cli",
          "sdk",
          "mcp",
          "system",
          "scheduler"
        ]
      },
      "Draft": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "object",
          "record_id",
          "collection_id",
          "collection",
          "base_revision",
          "revision",
          "data",
          "changed_fields",
          "schedule",
          "created_by",
          "edited_by",
          "created_at",
          "updated_at"
        ],
        "description": "Changes to a record's content that wait until they are merged into\nit, now or at `schedule.merge_at`. Content only: whether the record\nis live is its publication and schedule.\n",
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "drf_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "draft"
          },
          "record_id": {
            "type": "string"
          },
          "collection_id": {
            "type": "string"
          },
          "collection": {
            "type": "string",
            "description": "The collection slug."
          },
          "base_revision": {
            "type": "integer",
            "description": "The record's revision when the draft started. Fields the record\nchanged since keep their values at the merge, unless the draft\nchanges them too; compare with `GET /v1/records/{id}/diff?from=<base_revision>`.\n"
          },
          "revision": {
            "type": "integer",
            "description": "The draft's own revision, 1 when started and one more per change; also returned as the ETag."
          },
          "data": {
            "description": "The record's values as they read after the merge.",
            "$ref": "#/components/schemas/RecordData"
          },
          "changed_fields": {
            "type": "array",
            "description": "Keys of the fields the draft changes.",
            "items": {
              "type": "string"
            }
          },
          "schedule": {
            "$ref": "#/components/schemas/DraftSchedule"
          },
          "created_by": {
            "$ref": "#/components/schemas/Actor"
          },
          "edited_by": {
            "type": "array",
            "description": "Everyone who changed it since, in order.",
            "items": {
              "$ref": "#/components/schemas/Actor"
            }
          },
          "expanded": {
            "type": "object",
            "description": "Only with `expand`, as on a record, for the values after the merge.",
            "additionalProperties": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/Record"
                },
                {
                  "$ref": "#/components/schemas/Asset"
                },
                {
                  "type": "null"
                },
                {
                  "type": "array",
                  "items": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/Record"
                      },
                      {
                        "$ref": "#/components/schemas/Asset"
                      }
                    ]
                  }
                }
              ]
            }
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "DraftSchedule": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "merge_at",
          "last_error"
        ],
        "description": "When the draft merges on its own (within a minute of the time), set\nwith `PUT /v1/drafts/{draft_id}/schedule`. `last_error` explains the\nlast scheduled merge that could not be made, until a new one is set.\n",
        "properties": {
          "merge_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "DraftScheduleUpdate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "merge_at"
        ],
        "properties": {
          "merge_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "DraftCreate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "data": {
            "$ref": "#/components/schemas/RecordData"
          },
          "from_revision": {
            "type": "integer",
            "minimum": 1,
            "description": "Start from this revision's values instead of the record's current ones."
          }
        }
      },
      "DraftList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Draft"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "MergedDraft": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "created_at",
          "created_by",
          "edited_by"
        ],
        "description": "The draft a `merge` revision merged, which is gone since.",
        "properties": {
          "id": {
            "type": "string"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "created_by": {
            "$ref": "#/components/schemas/Actor"
          },
          "edited_by": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Actor"
            }
          }
        }
      },
      "RecordData": {
        "type": "object",
        "description": "Field values keyed by field `key`.\n\nA rich text value is written as Markdown (GitHub Flavored, a string)\nor as a ProseMirror JSON document (`{\"type\": \"doc\", \"content\": [...]}`),\nand stored and read as the document (`rich_text` reads it as HTML or\nMarkdown). Markdown is converted as closely as the vocabulary allows:\nheadings below h3 become h3, task list items plain items, footnotes and\nraw HTML text. A document uses the web editor's vocabulary (Tiptap's\nStarterKit and tables) and nothing else; another name is refused with\n`invalid_format`, naming ours where one fits (`strong` is `bold`):\n\n- blocks: `paragraph`, `heading` (`level` 1-3), `blockquote`,\n  `bulletList` and `orderedList` (`start`, `type`) of `listItem`\n  (starting with a paragraph), `codeBlock` (`language`),\n  `horizontalRule`, and `table` of `tableRow` of `tableHeader` or\n  `tableCell` (`colspan`, `rowspan`, `colwidth`, `align`); any block\n  may have `dir` (`auto`, `ltr`, `rtl`);\n- inline: `text` (non-empty) and `hardBreak`;\n- marks on text: `bold`, `italic`, `strike`, `underline`, `code` (alone),\n  and `link` (`href`, and `target`, `rel`, `class`, `title`); a link's\n  `href` is an `http`, `https`, `mailto`, `tel` or relative URL.\n\nAn image of an asset is `{\"type\": \"image\", \"attrs\": {\"asset_id\":\n\"ast_...\", \"alt\": \"...\"}}` (in Markdown `![alt](ast_...)`, or the\nasset's `image_url`), between the document's blocks (not inside a list,\nquote or table), at most 100 per document (`too_many_images`); a newly\nshown image must be an uploaded JPEG, PNG, GIF, WebP, AVIF or SVG of\nthe project (`invalid_reference`, `type_not_accepted`). `expand` embeds\nthe assets, and published-only keys can read the images of published\nrecords. A record holds at\nmost 2,000,000 bytes of values, all fields together (`too_large` on\n`data`); one already larger can still be edited without growing.\n",
        "additionalProperties": true,
        "examples": [
          {
            "title": "Introducing Foo",
            "body": {
              "type": "doc",
              "content": []
            }
          }
        ]
      },
      "Record": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "object",
          "collection_id",
          "collection",
          "published_at",
          "revision",
          "schema_version",
          "deleted_at",
          "purge_after",
          "history_pruned_through",
          "data",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "rec_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "record"
          },
          "collection_id": {
            "type": "string"
          },
          "collection": {
            "type": "string",
            "description": "The collection slug."
          },
          "published_at": {
            "description": "When the record was published; null while it is unpublished.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "revision": {
            "type": "integer",
            "description": "Current revision number; also returned as the ETag."
          },
          "schema_version": {
            "type": "integer"
          },
          "history_pruned_through": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Revisions up to this number (except revision 1) were removed by the plan's history retention."
          },
          "deleted_at": {
            "description": "When the record was soft-deleted; null unless it is.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "purge_after": {
            "description": "When a soft-deleted record is removed for good, unless restored first.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "data": {
            "$ref": "#/components/schemas/RecordData"
          },
          "expanded": {
            "type": "object",
            "description": "Only with `expand`: what each requested relation, asset or rich\ntext field points at, keyed by field key: records for\nrelation fields, assets for asset fields. A single value is the object, or null when\nit no longer exists; a multiple value is a list of those that still\nexist. For a rich text field, the list of assets its images show,\nin document order, leaving out those that no longer exist.\nExpanded records are not expanded further.\n",
            "additionalProperties": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/Record"
                },
                {
                  "$ref": "#/components/schemas/Asset"
                },
                {
                  "type": "null"
                },
                {
                  "type": "array",
                  "items": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/Record"
                      },
                      {
                        "$ref": "#/components/schemas/Asset"
                      }
                    ]
                  }
                }
              ]
            }
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "RecordWrite": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/RecordData"
          }
        }
      },
      "RecordCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/RecordData"
          },
          "upsert_on": {
            "type": "string",
            "description": "The key of a `unique` field (a slug, or a field with `unique` on)\nwhose value `data` includes: update the record that has it, or\ncreate one.\n",
            "examples": [
              "slug"
            ]
          }
        }
      },
      "RecordList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Record"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "Change": {
        "type": "object",
        "description": "One change between two states. Field changes carry `field` (current API\nkey) and the stable `field_id`; attribute changes (`published_at`,\n`deleted_at`) carry `attribute`.\n",
        "additionalProperties": false,
        "required": [
          "kind"
        ],
        "properties": {
          "field": {
            "type": [
              "string",
              "null"
            ],
            "description": "The field's key now, after any rename (its last key if it was deleted); null if the field no longer exists."
          },
          "field_id": {
            "type": "string"
          },
          "field_deleted": {
            "type": "boolean",
            "description": "Whether the field has been deleted since."
          },
          "attribute": {
            "type": "string",
            "enum": [
              "published_at",
              "deleted_at"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "added",
              "changed",
              "removed"
            ]
          },
          "before": {},
          "after": {}
        }
      },
      "RecordRevision": {
        "allOf": [
          {
            "$ref": "#/components/schemas/RecordRevisionProperties"
          }
        ],
        "unevaluatedProperties": false
      },
      "RecordRevisionProperties": {
        "type": "object",
        "required": [
          "id",
          "object",
          "record_id",
          "revision",
          "operation",
          "actor",
          "via",
          "note",
          "schema_version",
          "reverted_to_revision",
          "changed_fields",
          "redacted_fields",
          "draft",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "rev_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "record_revision"
          },
          "record_id": {
            "type": "string"
          },
          "revision": {
            "type": "integer"
          },
          "operation": {
            "$ref": "#/components/schemas/RecordRevisionOperation"
          },
          "actor": {
            "$ref": "#/components/schemas/Actor"
          },
          "via": {
            "$ref": "#/components/schemas/Via"
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "schema_version": {
            "type": "integer"
          },
          "reverted_to_revision": {
            "type": [
              "integer",
              "null"
            ]
          },
          "changed_fields": {
            "type": "array",
            "description": "Keys of changed fields, and changed attributes.",
            "items": {
              "type": "string"
            }
          },
          "redacted_fields": {
            "type": "array",
            "description": "Keys of fields whose values in this revision were redacted (owners\nand admins redact them in the web app); those values read\n`{\"$redacted\": true}`.\n",
            "items": {
              "type": "string"
            }
          },
          "draft": {
            "description": "For a `merge`, the draft it merged, with who started and edited it; null otherwise.",
            "anyOf": [
              {
                "$ref": "#/components/schemas/MergedDraft"
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "RecordRevisionDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/RecordRevisionProperties"
          },
          {
            "type": "object",
            "required": [
              "published_at",
              "data",
              "changes"
            ],
            "properties": {
              "published_at": {
                "$ref": "#/components/schemas/NullableTimestamp"
              },
              "data": {
                "$ref": "#/components/schemas/RecordData"
              },
              "changes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Change"
                }
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "RecordRevisionList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RecordRevision"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "RecordDiff": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "record_id",
          "from",
          "to",
          "changes"
        ],
        "properties": {
          "object": {
            "const": "record_diff"
          },
          "record_id": {
            "type": "string"
          },
          "from": {
            "type": "integer"
          },
          "to": {
            "type": "integer"
          },
          "changes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Change"
            }
          }
        }
      },
      "RevertPreview": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "record_id",
          "to_revision",
          "data",
          "changes"
        ],
        "properties": {
          "object": {
            "const": "revert_preview"
          },
          "record_id": {
            "type": "string"
          },
          "to_revision": {
            "type": "integer"
          },
          "data": {
            "$ref": "#/components/schemas/RecordData"
          },
          "changes": {
            "type": "array",
            "description": "What the revert would change. Rich text values read as `rich_text` asks, like `data`; a change that HTML or Markdown can't show (an underline, in Markdown) reads the same on both sides.",
            "items": {
              "$ref": "#/components/schemas/Change"
            }
          }
        }
      },
      "FeatureFlags": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "organization_id",
          "project_id",
          "flags"
        ],
        "properties": {
          "object": {
            "const": "feature_flags"
          },
          "organization_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "flags": {
            "type": "object",
            "description": "Flag name to enabled, for every registered flag the caller may see.",
            "additionalProperties": {
              "type": "boolean"
            }
          }
        }
      },
      "Principal": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "type",
          "user",
          "api_key"
        ],
        "properties": {
          "object": {
            "const": "principal"
          },
          "type": {
            "type": "string",
            "enum": [
              "user",
              "api_key"
            ]
          },
          "user": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "id",
                  "email",
                  "name",
                  "staff"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "staff": {
                    "type": "boolean",
                    "description": "Whether the user is Nohead staff."
                  }
                }
              }
            ]
          },
          "api_key": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "id",
                  "name",
                  "scopes",
                  "published_only",
                  "project_id",
                  "expires_at"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ApiKeyScope"
                    }
                  },
                  "published_only": {
                    "$ref": "#/components/schemas/PublishedOnly"
                  },
                  "project_id": {
                    "type": "string"
                  },
                  "expires_at": {
                    "$ref": "#/components/schemas/NullableTimestamp"
                  }
                }
              }
            ]
          }
        }
      },
      "SearchResults": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Record"
            }
          },
          "meta": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "next_cursor",
              "has_more",
              "total_estimate"
            ],
            "properties": {
              "next_cursor": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "has_more": {
                "type": "boolean"
              },
              "total_estimate": {
                "type": "integer",
                "description": "Approximate number of matches."
              }
            }
          }
        }
      },
      "SearchIndex": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "collection_id",
          "index",
          "status",
          "documents",
          "last_built_at",
          "rebuild_requested_at"
        ],
        "properties": {
          "object": {
            "const": "search_index"
          },
          "collection_id": {
            "type": "string"
          },
          "index": {
            "type": "string",
            "description": "The index's name in the search engine, which search tokens search\n(`indexUid` in Meilisearch's search API). Opaque; it never changes.\n"
          },
          "status": {
            "type": "string",
            "enum": [
              "building",
              "ready",
              "stale",
              "failed"
            ],
            "description": "`building` until first built; `stale` from the change that queues a rebuild until it has run; `failed` if the last rebuild failed (it is retried)."
          },
          "documents": {
            "type": "integer"
          },
          "last_built_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "rebuild_requested_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          }
        }
      },
      "WebhookEventType": {
        "type": "string",
        "description": "An event webhooks can subscribe to: the same names as the activity\nlog's actions. A subscription can also be every type of a resource\n(`record.*`, `draft.*`, `collection.*`, `field.*`, `asset.*`) or `*` for all.\n",
        "enum": [
          "record.created",
          "record.updated",
          "record.published",
          "record.unpublished",
          "record.deleted",
          "record.restored",
          "record.reverted",
          "record.redacted",
          "record.scheduled",
          "record.unscheduled",
          "record.schedule_failed",
          "draft.created",
          "draft.updated",
          "draft.discarded",
          "draft.scheduled",
          "draft.unscheduled",
          "draft.schedule_failed",
          "collection.created",
          "collection.updated",
          "collection.deleted",
          "collection.restored",
          "collection.fields_reordered",
          "field.created",
          "field.updated",
          "field.deleted",
          "field.restored",
          "field.migrated",
          "field.alias_removed",
          "asset.created",
          "asset.updated",
          "asset.deleted",
          "asset.restored",
          "asset.purged"
        ]
      },
      "WebhookSubscription": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          {
            "type": "string",
            "enum": [
              "record.*",
              "draft.*",
              "collection.*",
              "field.*",
              "asset.*",
              "*"
            ]
          }
        ]
      },
      "Webhook": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookProperties"
          }
        ],
        "unevaluatedProperties": false
      },
      "WebhookProperties": {
        "type": "object",
        "required": [
          "id",
          "object",
          "project_id",
          "url",
          "description",
          "event_types",
          "published_only",
          "enabled",
          "deleted_at",
          "purge_after",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "wh_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "webhook"
          },
          "project_id": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "event_types": {
            "type": "array",
            "description": "The subscribed event types and wildcards (`record.*`, or `*` for all).",
            "items": {
              "$ref": "#/components/schemas/WebhookSubscription"
            }
          },
          "published_only": {
            "type": "boolean",
            "description": "Send only events that change what a published-only API key can read: a record's change while it is published (or that publishes, unpublishes, deletes or restores it), schema changes, and changes to assets that published records use. Drafts, schedules, history redactions, uploads and purges are never sent. `webhook.test` always is."
          },
          "enabled": {
            "type": "boolean"
          },
          "deleted_at": {
            "description": "When the webhook was deleted; null unless it is.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "purge_after": {
            "description": "When a deleted webhook is removed for good, with its delivery log, unless restored first.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "WebhookWithSecret": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookProperties"
          },
          {
            "type": "object",
            "required": [
              "secret"
            ],
            "properties": {
              "secret": {
                "type": "string",
                "description": "The signing secret (`whsec_...`). Keep it private."
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "WebhookSecret": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookSecretProperties"
          }
        ],
        "unevaluatedProperties": false
      },
      "WebhookSecretProperties": {
        "type": "object",
        "required": [
          "id",
          "object",
          "webhook_id",
          "expires_at",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "whs_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "webhook_secret"
          },
          "webhook_id": {
            "type": "string"
          },
          "expires_at": {
            "description": "When it stops signing deliveries; null for the newest secret.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "WebhookSecretWithValue": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookSecretProperties"
          },
          {
            "type": "object",
            "required": [
              "secret"
            ],
            "properties": {
              "secret": {
                "type": "string",
                "description": "The signing secret (`whsec_...`), shown only when it is added. Keep it private."
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "WebhookSecretList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookSecret"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "RecordBatchRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "action",
          "record_ids"
        ],
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "publish",
              "unpublish",
              "delete",
              "restore",
              "update"
            ]
          },
          "record_ids": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "uniqueItems": true,
            "items": {
              "type": "string"
            }
          },
          "data": {
            "type": "object",
            "description": "For `update`, the fields to set on every record (null clears one).",
            "additionalProperties": true
          }
        }
      },
      "RecordBatch": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "action",
          "succeeded",
          "failed",
          "results"
        ],
        "properties": {
          "object": {
            "const": "record_batch"
          },
          "action": {
            "type": "string",
            "enum": [
              "publish",
              "unpublish",
              "delete",
              "restore",
              "update"
            ]
          },
          "succeeded": {
            "type": "integer"
          },
          "failed": {
            "type": "integer"
          },
          "results": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "id",
                    "status",
                    "changed",
                    "record"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "const": "succeeded"
                    },
                    "changed": {
                      "type": "boolean",
                      "description": "False when the record was already in that state (no revision)."
                    },
                    "record": {
                      "$ref": "#/components/schemas/Record"
                    }
                  }
                },
                {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "id",
                    "status",
                    "error"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "const": "failed"
                    },
                    "error": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "type",
                        "message"
                      ],
                      "properties": {
                        "type": {
                          "$ref": "#/components/schemas/ErrorType"
                        },
                        "message": {
                          "type": "string"
                        },
                        "details": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ErrorDetail"
                          }
                        }
                      }
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "AuditEvent": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "object",
          "organization_id",
          "project",
          "type",
          "resource",
          "actor",
          "via",
          "note",
          "metadata",
          "request_id",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "evt_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "event"
          },
          "organization_id": {
            "type": "string"
          },
          "project": {
            "description": "The project the event belongs to, or null for organization-level events.",
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "id",
                  "name"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                }
              }
            ]
          },
          "type": {
            "type": "string",
            "description": "`<resource>.<verb>`, e.g. `record.published`, `field.updated`,\n`api_key.created`, `member.role_changed`: a webhook event's type\ntoo, for the events webhooks get.\n",
            "examples": [
              "record.published"
            ]
          },
          "resource": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type",
              "id"
            ],
            "properties": {
              "type": {
                "type": "string",
                "description": "What the event is about, such as `record`, `draft`, `collection`, `field`, `asset` or `webhook`; a field's change names its collection in `metadata.collection_id`.",
                "examples": [
                  "record"
                ]
              },
              "id": {
                "type": "string",
                "description": "The resource's public ID (or key, for feature flags)."
              }
            }
          },
          "actor": {
            "$ref": "#/components/schemas/Actor"
          },
          "via": {
            "description": "The client the change came through, when known.",
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Via"
              }
            ]
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "description": "The change note (`Nohead-Change-Note`) the change was made with,\nread from the revision or schema change the event references, so\nrecord and schema events have one when their change did; null\notherwise, and once a revision's history is pruned.\n",
            "examples": [
              "Clearer title"
            ]
          },
          "metadata": {
            "type": "object",
            "description": "Small, action-specific references, e.g. `revision_id` and\n`collection_id` for record events, `schema_change_id` for schema\nevents, `changed` attribute names for updates (field keys for a\ndraft's). Never content.\n",
            "additionalProperties": true
          },
          "request_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AuditEventList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuditEvent"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "WebhookList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "WebhookCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "url",
          "event_types"
        ],
        "properties": {
          "url": {
            "type": "string",
            "description": "An https URL on the public internet."
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "event_types": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/WebhookSubscription"
            }
          },
          "published_only": {
            "type": "boolean",
            "description": "Send only events that change what a published-only API key can read (`false` by default). It can't be combined with event types it never sends, such as `draft.*`."
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "WebhookUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "url": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "event_types": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/WebhookSubscription"
            }
          },
          "published_only": {
            "type": "boolean",
            "description": "Send only events that change what a published-only API key can read (`false` by default). It can't be combined with event types it never sends, such as `draft.*`."
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "WebhookDeliveryProperties": {
        "type": "object",
        "required": [
          "id",
          "object",
          "webhook_id",
          "event",
          "status",
          "attempts_count",
          "last_status_code",
          "last_error",
          "last_attempt_at",
          "next_attempt_at",
          "succeeded_at",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "whd_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "webhook_delivery"
          },
          "webhook_id": {
            "type": "string"
          },
          "event": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "type",
              "created_at"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "The event ID, sent as `webhook-id`; the same on every attempt."
              },
              "type": {
                "type": "string"
              },
              "created_at": {
                "$ref": "#/components/schemas/Timestamp"
              }
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "succeeded",
              "failed"
            ],
            "description": "`pending` until an attempt gets a 2xx response; `failed` after 8 attempts over about a day."
          },
          "attempts_count": {
            "type": "integer"
          },
          "last_status_code": {
            "type": [
              "integer",
              "null"
            ]
          },
          "last_error": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_attempt_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "next_attempt_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "succeeded_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "WebhookDelivery": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookDeliveryProperties"
          }
        ],
        "unevaluatedProperties": false
      },
      "WebhookDeliveryDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookDeliveryProperties"
          },
          {
            "type": "object",
            "required": [
              "payload",
              "attempts"
            ],
            "properties": {
              "payload": {
                "$ref": "#/components/schemas/WebhookEventPayload"
              },
              "attempts": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "number",
                    "status_code",
                    "error",
                    "duration_ms",
                    "response_body",
                    "created_at"
                  ],
                  "properties": {
                    "number": {
                      "type": "integer"
                    },
                    "status_code": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "error": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "duration_ms": {
                      "type": "integer"
                    },
                    "response_body": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The first 2 KB of the response."
                    },
                    "created_at": {
                      "$ref": "#/components/schemas/Timestamp"
                    }
                  }
                }
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "WebhookDeliveryList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDelivery"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "WebhookEventPayload": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "object",
          "type",
          "created_at",
          "project_id",
          "actor",
          "via",
          "data"
        ],
        "description": "The JSON body of every webhook request. It is rendered from the event's\nhistory each time it is sent or shown, so redacted values are redacted\nin it too. `data` depends on the `type`.\n",
        "properties": {
          "id": {
            "type": "string",
            "description": "The event's ID, also sent as `webhook-id`; dedupe by it.",
            "examples": [
              "evt_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "event"
          },
          "type": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/WebhookEventType"
              },
              {
                "const": "webhook.test"
              }
            ]
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "project_id": {
            "type": "string"
          },
          "actor": {
            "description": "Who made the change.",
            "allOf": [
              {
                "$ref": "#/components/schemas/Actor"
              }
            ]
          },
          "via": {
            "description": "The client the change came through (null when not known). An\nintegration that writes back can skip changes made with its own API\nkey (`actor`).\n",
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Via"
              }
            ]
          },
          "data": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/RecordEventData"
              },
              {
                "$ref": "#/components/schemas/DraftEventData"
              },
              {
                "$ref": "#/components/schemas/AssetEventData"
              },
              {
                "$ref": "#/components/schemas/SchemaEventData"
              },
              {
                "$ref": "#/components/schemas/FieldAliasEventData"
              },
              {
                "$ref": "#/components/schemas/WebhookTestEventData"
              }
            ]
          }
        }
      },
      "RecordEventData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "record",
          "revision",
          "revision_id"
        ],
        "description": "`record.*`: the record as the change's revision left it, or as it is now for events without a revision (`record.scheduled`, `record.unscheduled`, `record.schedule_failed`, `record.redacted`).",
        "properties": {
          "record": {
            "description": "Null once the record is purged.",
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Record"
              }
            ]
          },
          "revision": {
            "type": [
              "integer",
              "null"
            ]
          },
          "revision_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Null for events without a revision."
          },
          "draft_id": {
            "type": "string",
            "description": "On the `record.updated` of a merged draft, the draft it merged."
          }
        }
      },
      "DraftEventData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "draft",
          "draft_id",
          "record_id"
        ],
        "description": "`draft.*`: the draft as it is now.",
        "properties": {
          "draft": {
            "description": "Null once merged or discarded, and while its record is deleted.",
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Draft"
              }
            ]
          },
          "draft_id": {
            "type": "string",
            "description": "The draft's ID, also once it is gone."
          },
          "record_id": {
            "type": "string"
          }
        }
      },
      "AssetEventData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "asset"
        ],
        "description": "`asset.*`: the asset as it is now.",
        "properties": {
          "asset": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Asset"
              },
              {
                "type": "object",
                "description": "Only its ID once it is purged.",
                "additionalProperties": false,
                "required": [
                  "id",
                  "object"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "object": {
                    "const": "asset"
                  }
                }
              }
            ]
          }
        }
      },
      "SchemaEventData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "collection",
          "schema_change"
        ],
        "description": "`collection.*` and `field.*` (but `field.alias_removed`): the collection as the change left it, and the change.",
        "properties": {
          "collection": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "object",
              "slug",
              "name",
              "schema_version",
              "deleted_at"
            ],
            "description": "Only `id` and `object` are known once the schema change is gone (the collection was purged).",
            "properties": {
              "id": {
                "type": "string"
              },
              "object": {
                "const": "collection"
              },
              "slug": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "schema_version": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "deleted_at": {
                "$ref": "#/components/schemas/NullableTimestamp"
              }
            }
          },
          "field_id": {
            "type": "string",
            "description": "`field.*`: the field that changed."
          },
          "schema_change": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "id",
                  "operation",
                  "from_version",
                  "to_version"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "operation": {
                    "type": "string"
                  },
                  "from_version": {
                    "type": "integer"
                  },
                  "to_version": {
                    "type": "integer"
                  }
                }
              }
            ]
          }
        }
      },
      "FieldAliasEventData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "field"
        ],
        "description": "`field.alias_removed`: the field.",
        "properties": {
          "field": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Field"
              }
            ]
          }
        }
      },
      "WebhookTestEventData": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "webhook"
        ],
        "description": "`webhook.test`: the webhook it was sent to.",
        "properties": {
          "webhook": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Webhook"
              }
            ]
          }
        }
      },
      "Asset": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AssetProperties"
          }
        ],
        "unevaluatedProperties": false
      },
      "AssetKind": {
        "type": "string",
        "enum": [
          "image",
          "video",
          "audio",
          "document",
          "other"
        ]
      },
      "AssetUpdate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "filename": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Control characters are removed and path separators become `_`, as on upload."
          },
          "alt": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1000,
            "description": "Surrounding whitespace is removed; empty or null clears it."
          }
        }
      },
      "AssetProperties": {
        "type": "object",
        "required": [
          "id",
          "object",
          "project_id",
          "filename",
          "alt",
          "content_type",
          "byte_size",
          "width",
          "height",
          "status",
          "deleted_at",
          "purge_after",
          "image_url",
          "preview_url",
          "file_url",
          "media_url",
          "uploaded_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "ast_01J9ZQ3F8X5W2K7M4N6P0R1S2T"
            ]
          },
          "object": {
            "const": "asset"
          },
          "project_id": {
            "type": "string"
          },
          "filename": {
            "type": "string",
            "description": "The filename, any Unicode, as uploaded unless renamed since. Downloads use it."
          },
          "alt": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1000,
            "description": "Alternative text, saying what an image shows; null until set. The default wherever the asset is used."
          },
          "content_type": {
            "type": "string",
            "examples": [
              "image/png"
            ]
          },
          "byte_size": {
            "type": "integer"
          },
          "width": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Pixel width, for images."
          },
          "height": {
            "type": [
              "integer",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "ready",
              "failed"
            ],
            "description": "`pending` until the upload is completed; only `ready` assets can be used in records."
          },
          "deleted_at": {
            "description": "When the asset was deleted; null unless it is.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "purge_after": {
            "description": "When a deleted asset and its file are removed for good, unless restored or purged first.",
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The URL of the whole image, for ready images (JPEG, PNG, GIF, WebP,\nAVIF or SVG), deleted ones included until they are purged; null\notherwise. Image URLs are open and never expire. An SVG is served\nas SVG without its scripts, unless a format such as `@webp`\nrasterizes it. For a rendition,\nwrite [imgproxy processing options](https://docs.imgproxy.net/usage/processing)\nbefore `/plain/`, and a format after `@`: for example\n`https://images.nohead.io/rs:fill:800:600/g:sm/plain/…@webp`. Renditions\nare at most 4096 pixels a side, from originals of at most 50\nmegapixels. Options that would return the file as stored (`raw`,\n`skip_processing`, `strip_metadata`) are refused.\n",
            "examples": [
              "https://images.nohead.io/plain/0199f5c2-7b1e-7c3a-9d4f-2a6b8c0e1f3d/0199f5c2-8a2d-7e4b-b1c3-5d7e9f1a2b4c"
            ]
          },
          "preview_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The URL of a small rendition (fits in 640×640, WebP), for ready images and SVGs (rasterized), deleted ones included until they are purged; null otherwise."
          },
          "file_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The URL of the file as uploaded, for ready assets of any type,\ndeleted ones included until they are purged; null otherwise. It\ndownloads the file under its `filename` (a rename applies within a\nminute or so), is open and never expires, and is cached on a CDN.\n",
            "examples": [
              "https://files.nohead.io/0199f5c2-7b1e-7c3a-9d4f-2a6b8c0e1f3d/0199f5c2-8a2d-7e4b-b1c3-5d7e9f1a2b4c"
            ]
          },
          "media_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The URL that plays a ready video or audio file inline, for\n`<video>` and `<audio>` (with range requests, so players can seek),\ndeleted ones included until they are purged: MP4, QuickTime, M4A,\n3GP, WebM, Matroska, MP3, AAC, FLAC, WAV and Ogg (whose content is\nchecked when the upload completes). Null for other types, which\n`file_url` downloads.\nOpen, never expiring and cached on a CDN, like `file_url`.\n",
            "examples": [
              "https://media.nohead.io/0199f5c2-7b1e-7c3a-9d4f-2a6b8c0e1f3d/0199f5c2-8a2d-7e4b-b1c3-5d7e9f1a2b4c"
            ]
          },
          "uploaded_at": {
            "$ref": "#/components/schemas/NullableTimestamp"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "AssetList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Asset"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ListMeta"
          }
        }
      },
      "AssetUsage": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "asset_id",
          "records",
          "published",
          "uses"
        ],
        "properties": {
          "object": {
            "const": "asset_usage"
          },
          "asset_id": {
            "type": "string"
          },
          "records": {
            "type": "integer",
            "minimum": 0,
            "description": "Undeleted records that use the asset, in their content or their draft."
          },
          "published": {
            "type": "integer",
            "minimum": 0,
            "description": "Of those, the published ones whose content uses it (what sites show)."
          },
          "uses": {
            "type": "array",
            "maxItems": 10,
            "description": "The most recently updated records that use the asset.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "record",
                "fields"
              ],
              "properties": {
                "record": {
                  "$ref": "#/components/schemas/Record"
                },
                "fields": {
                  "type": "array",
                  "minItems": 1,
                  "description": "Keys of the record's fields that use the asset, in its content or its draft.",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      },
      "AssetUploadCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "filename",
          "content_type",
          "byte_size"
        ],
        "properties": {
          "filename": {
            "type": "string",
            "maxLength": 255
          },
          "content_type": {
            "type": "string",
            "examples": [
              "image/jpeg"
            ]
          },
          "byte_size": {
            "type": "integer",
            "minimum": 1,
            "description": "Exact size of the file in bytes, at most the plan's largest upload (10 MB on Free, 100 MB on paid plans)."
          }
        }
      },
      "FieldOrder": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "object",
          "collection_id",
          "field_ids"
        ],
        "properties": {
          "object": {
            "const": "field_order"
          },
          "collection_id": {
            "type": "string"
          },
          "field_ids": {
            "type": "array",
            "description": "The collection's active fields, first to last.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "AssetWithUpload": {
        "description": "A new asset with where to upload its file, returned only when it is created.",
        "allOf": [
          {
            "$ref": "#/components/schemas/AssetProperties"
          },
          {
            "type": "object",
            "required": [
              "upload"
            ],
            "properties": {
              "upload": {
                "$ref": "#/components/schemas/AssetUploadTarget"
              }
            }
          }
        ],
        "unevaluatedProperties": false
      },
      "AssetUploadTarget": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "method",
          "url",
          "headers",
          "expires_at"
        ],
        "properties": {
          "method": {
            "const": "PUT"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "headers": {
            "type": "object",
            "description": "Headers to send with the upload.",
            "additionalProperties": {
              "type": "string"
            }
          },
          "expires_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "ApiKeyScope": {
        "type": "string",
        "description": "What a project API key may do. `records:write` also publishes, unpublishes and schedules records. `webhooks:read` includes delivery payloads and `webhooks:write` can subscribe an endpoint to every event, so both give access to the record, schema and asset data in events, unpublished records included; published-only keys cannot have them.",
        "enum": [
          "records:read",
          "records:write",
          "schema:read",
          "schema:write",
          "assets:read",
          "assets:write",
          "search:read",
          "webhooks:read",
          "webhooks:write",
          "audit:read"
        ]
      },
      "PublishedOnly": {
        "type": "boolean",
        "default": false,
        "description": "The key sees published records only, for sites and apps: lists, reads, search and expanded relations leave out unpublished and deleted records, and history is not available. Only read scopes (records:read, schema:read, assets:read, search:read) are allowed."
      },
      "ErrorType": {
        "type": "string",
        "enum": [
          "invalid_request",
          "authentication_error",
          "plan_limit_exceeded",
          "authorization_error",
          "not_found",
          "conflict",
          "precondition_failed",
          "validation_error",
          "rate_limited",
          "internal_error",
          "service_unavailable"
        ]
      },
      "ErrorDetail": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "field": {
            "type": "string",
            "description": "Key of the offending field or parameter, when applicable."
          },
          "code": {
            "type": "string",
            "description": "Machine-readable error code, e.g. `required`."
          },
          "message": {
            "type": "string"
          },
          "usage": {
            "type": "integer",
            "description": "Current usage, for `plan_limit` details."
          },
          "limit": {
            "type": "integer",
            "description": "The plan's limit, for `plan_limit` details."
          },
          "current_revision": {
            "type": "integer",
            "description": "The resource's current revision, for `revision_mismatch` details."
          },
          "record_id": {
            "type": "string",
            "description": "The record that already has the value, for `taken` details."
          },
          "draft_id": {
            "type": "string",
            "description": "The record's draft, for `draft_exists` and `draft_pending` details."
          }
        }
      },
      "Error": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "type",
              "message",
              "request_id"
            ],
            "properties": {
              "type": {
                "$ref": "#/components/schemas/ErrorType"
              },
              "message": {
                "type": "string"
              },
              "request_id": {
                "$ref": "#/components/schemas/RequestId"
              },
              "details": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "responses": {
      "FieldOrder": {
        "description": "The collection's active fields, in order.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/FieldOrder"
            }
          }
        }
      },
      "Record": {
        "description": "The record.",
        "headers": {
          "ETag": {
            "$ref": "#/components/headers/ETag"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Record"
            }
          }
        }
      },
      "Draft": {
        "description": "The draft.",
        "headers": {
          "ETag": {
            "$ref": "#/components/headers/ETag"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Draft"
            }
          }
        }
      },
      "DraftCreated": {
        "description": "The started draft.",
        "headers": {
          "ETag": {
            "$ref": "#/components/headers/ETag"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Draft"
            }
          }
        }
      },
      "DraftList": {
        "description": "A page of drafts.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/DraftList"
            }
          }
        }
      },
      "RecordSchedule": {
        "description": "The record's schedule.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RecordSchedule"
            }
          }
        }
      },
      "RecordCreated": {
        "description": "The created record.",
        "headers": {
          "ETag": {
            "$ref": "#/components/headers/ETag"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Record"
            }
          }
        }
      },
      "BadRequest": {
        "description": "The request was malformed: unparseable JSON, an invalid query parameter, or a body key the operation doesn't take (detail code `unknown_parameter`, naming the key).",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Authentication is missing or invalid.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PlanLimitExceeded": {
        "description": "The change would exceed a hard limit of the organization's plan. The\ndetail names the metric (`field`) with its `usage` and `limit`.\n",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The caller is not allowed to perform this action.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "The resource does not exist or is not visible to the caller.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "The request conflicts with current state.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PreconditionFailed": {
        "description": "The resource changed since the revision given in `If-Match`. Nothing was\nwritten; `details` includes the current revision.\n",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "precondition_failed",
                "message": "Record has changed since revision 6",
                "request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
                "details": [
                  {
                    "code": "revision_mismatch",
                    "message": "Current revision is 7",
                    "current_revision": 7
                  }
                ]
              }
            }
          }
        }
      },
      "ValidationFailed": {
        "description": "The request failed validation.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "validation_error",
                "message": "Record validation failed",
                "request_id": "req_01J9ZQ3F8X5W2K7M4N6P0R1S2T",
                "details": [
                  {
                    "field": "title",
                    "code": "required",
                    "message": "is required"
                  }
                ]
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests for this API key or user (or, with failing\ncredentials, this IP address). A published-only key is counted per\nclient IP. Wait `Retry-After` seconds; retries with the same `Idempotency-Key`\nare safe. On the Free plan, an organization's API keys are also\nrefused once its API requests reach the month's limit, with a\n`plan_limit` detail (`field` `api_requests`, `usage` and `limit`),\nuntil the next month (UTC) or an upgrade.\n",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          },
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "The service is temporarily unavailable.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}