diff --git a/api/databases/add-columns.mdx b/api/databases/add-columns.mdx
new file mode 100644
index 0000000000..0d1dd27192
--- /dev/null
+++ b/api/databases/add-columns.mdx
@@ -0,0 +1,11 @@
+---
+title: "Add columns"
+openapi: "/databases-openapi.json POST /databases/{projectId}/{databaseId}/col"
+keywords: ["databases", "columns", "schema"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
+
+See [column types](/databases/columns) for how each type validates values.
diff --git a/api/databases/create-database.mdx b/api/databases/create-database.mdx
new file mode 100644
index 0000000000..3b80cc4760
--- /dev/null
+++ b/api/databases/create-database.mdx
@@ -0,0 +1,9 @@
+---
+title: "Create database"
+openapi: "/databases-openapi.json POST /databases/{projectId}"
+keywords: ["databases", "create"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
diff --git a/api/databases/create-row.mdx b/api/databases/create-row.mdx
new file mode 100644
index 0000000000..f660805ebd
--- /dev/null
+++ b/api/databases/create-row.mdx
@@ -0,0 +1,9 @@
+---
+title: "Create row"
+openapi: "/databases-openapi.json POST /databases/{projectId}/{databaseId}/row"
+keywords: ["databases", "rows", "create"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
diff --git a/api/databases/delete-column.mdx b/api/databases/delete-column.mdx
new file mode 100644
index 0000000000..a869a6e764
--- /dev/null
+++ b/api/databases/delete-column.mdx
@@ -0,0 +1,13 @@
+---
+title: "Delete column"
+openapi: "/databases-openapi.json DELETE /databases/{projectId}/{databaseId}/col/{columnId}"
+keywords: ["databases", "columns"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
+
+
+ Deleting a column removes its value from every row. There is no undo.
+
diff --git a/api/databases/delete-database.mdx b/api/databases/delete-database.mdx
new file mode 100644
index 0000000000..3b1a742f9e
--- /dev/null
+++ b/api/databases/delete-database.mdx
@@ -0,0 +1,13 @@
+---
+title: "Delete database"
+openapi: "/databases-openapi.json DELETE /databases/{projectId}/{databaseId}"
+keywords: ["databases", "delete"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
+
+
+ This deletes every row in the database. There is no undo.
+
diff --git a/api/databases/delete-row.mdx b/api/databases/delete-row.mdx
new file mode 100644
index 0000000000..155aa2849d
--- /dev/null
+++ b/api/databases/delete-row.mdx
@@ -0,0 +1,9 @@
+---
+title: "Delete row"
+openapi: "/databases-openapi.json DELETE /databases/{projectId}/{databaseId}/row/{rowId}"
+keywords: ["databases", "rows", "delete"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
diff --git a/api/databases/get-changes.mdx b/api/databases/get-changes.mdx
new file mode 100644
index 0000000000..f530229df4
--- /dev/null
+++ b/api/databases/get-changes.mdx
@@ -0,0 +1,11 @@
+---
+title: "Get changes"
+openapi: "/databases-openapi.json GET /databases/{projectId}/{databaseId}/changes"
+keywords: ["databases", "changes", "change log"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
+
+For a push-based stream of the same events, see [live updates](/databases/live-updates).
diff --git a/api/databases/get-database.mdx b/api/databases/get-database.mdx
new file mode 100644
index 0000000000..35a70bcff6
--- /dev/null
+++ b/api/databases/get-database.mdx
@@ -0,0 +1,9 @@
+---
+title: "Get database"
+openapi: "/databases-openapi.json GET /databases/{projectId}/{databaseId}"
+keywords: ["databases", "get"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
diff --git a/api/databases/get-row.mdx b/api/databases/get-row.mdx
new file mode 100644
index 0000000000..a04a082365
--- /dev/null
+++ b/api/databases/get-row.mdx
@@ -0,0 +1,9 @@
+---
+title: "Get row"
+openapi: "/databases-openapi.json GET /databases/{projectId}/{databaseId}/row/{rowId}"
+keywords: ["databases", "rows"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
diff --git a/api/databases/get-schema.mdx b/api/databases/get-schema.mdx
new file mode 100644
index 0000000000..41dfc872cb
--- /dev/null
+++ b/api/databases/get-schema.mdx
@@ -0,0 +1,9 @@
+---
+title: "Get schema"
+openapi: "/databases-openapi.json GET /databases/{projectId}/{databaseId}/col"
+keywords: ["databases", "schema", "columns"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
diff --git a/api/databases/list-databases.mdx b/api/databases/list-databases.mdx
new file mode 100644
index 0000000000..0100d7d9c2
--- /dev/null
+++ b/api/databases/list-databases.mdx
@@ -0,0 +1,9 @@
+---
+title: "List databases"
+openapi: "/databases-openapi.json GET /databases/{projectId}"
+keywords: ["databases", "list"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
diff --git a/api/databases/list-rows.mdx b/api/databases/list-rows.mdx
new file mode 100644
index 0000000000..18fd61c3af
--- /dev/null
+++ b/api/databases/list-rows.mdx
@@ -0,0 +1,22 @@
+---
+title: "List rows"
+openapi: "/databases-openapi.json GET /databases/{projectId}/{databaseId}/rows"
+keywords: ["databases", "rows", "filter", "sort", "cursor"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
+
+## Filtering
+
+Filter with one query parameter per column, `where[]=`. Values are coerced to the column type, so `where[col_x]=true` works on a boolean column and `where[col_x]=42` on a number column. For `multi_select` columns the filter matches rows whose array contains the value. `json` columns cannot be filtered.
+
+```bash
+curl "https://api.mintlify.com/v1/databases/$PROJECT_ID/$DATABASE_ID/rows?where\[col_qtxj9tuf\]=published&sort=col_8f2k1a0p:desc&limit=50" \
+ -H "Authorization: Bearer $MINT_API_KEY"
+```
+
+## Paging
+
+Pass `nextCursor` from one page as `cursor` on the next. Cursors are keyset based, so a row inserted or deleted between two requests is never skipped or repeated.
diff --git a/api/databases/update-column.mdx b/api/databases/update-column.mdx
new file mode 100644
index 0000000000..63181206bd
--- /dev/null
+++ b/api/databases/update-column.mdx
@@ -0,0 +1,9 @@
+---
+title: "Update column"
+openapi: "/databases-openapi.json PATCH /databases/{projectId}/{databaseId}/col/{columnId}"
+keywords: ["databases", "columns", "rename"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
diff --git a/api/databases/update-row.mdx b/api/databases/update-row.mdx
new file mode 100644
index 0000000000..d34632cd9f
--- /dev/null
+++ b/api/databases/update-row.mdx
@@ -0,0 +1,13 @@
+---
+title: "Update row"
+openapi: "/databases-openapi.json PATCH /databases/{projectId}/{databaseId}/row/{rowId}"
+keywords: ["databases", "rows", "If-Match", "revision"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
+
+## Conditional writes
+
+Every row carries a `rev` that increments on each update. Send `If-Match: ` with the value you last read. If someone else updated the row in between, the response is `409` with `code: "stale_revision"` and the current `rev`, and nothing is written.
diff --git a/api/databases/upsert-rows.mdx b/api/databases/upsert-rows.mdx
new file mode 100644
index 0000000000..1b2831661d
--- /dev/null
+++ b/api/databases/upsert-rows.mdx
@@ -0,0 +1,13 @@
+---
+title: "Bulk upsert rows"
+openapi: "/databases-openapi.json PUT /databases/{projectId}/{databaseId}/rows"
+keywords: ["databases", "rows", "bulk", "upsert", "import"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
+
+
+ Choose your own row ids, for example a UUID derived from your product's primary key, so repeated pipeline runs update rows instead of duplicating them.
+
diff --git a/databases-openapi.json b/databases-openapi.json
new file mode 100644
index 0000000000..889080b752
--- /dev/null
+++ b/databases-openapi.json
@@ -0,0 +1,1568 @@
+{
+ "openapi": "3.0.1",
+ "info": {
+ "title": "Mintlify Databases API",
+ "description": "Create databases, manage their columns, and read and write rows. Databases are in early access and enabled per project.",
+ "version": "1.0.0"
+ },
+ "servers": [
+ {
+ "url": "https://api.mintlify.com/v1"
+ }
+ ],
+ "security": [
+ {
+ "bearerAuth": []
+ }
+ ],
+ "paths": {
+ "/databases/{projectId}": {
+ "get": {
+ "summary": "List databases",
+ "operationId": "listDatabases",
+ "description": "List the databases on a project, oldest first.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The project's databases.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "databases"
+ ],
+ "properties": {
+ "databases": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Database"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "summary": "Create database",
+ "operationId": "createDatabase",
+ "description": "Create a database. The slug is derived from the name unless you pass one. It is used by the `` component to reference the database from a page.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/CreateDatabase"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "The database. `status` is `ready` once storage is initialised.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Database"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "409": {
+ "description": "A database with this slug already exists on the project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "422": {
+ "description": "The name is empty or no slug can be derived from it.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ValidationError"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/databases/{projectId}/{databaseId}": {
+ "get": {
+ "summary": "Get database",
+ "operationId": "getDatabase",
+ "description": "Get a database. If the database is still `initializing`, this call retries initialisation.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The database.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Database"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "summary": "Delete database",
+ "operationId": "deleteDatabase",
+ "description": "Delete a database and every row in it. There is no undo.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Deleted.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "deleted": {
+ "type": "string",
+ "format": "uuid"
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/databases/{projectId}/{databaseId}/col": {
+ "get": {
+ "summary": "Get schema",
+ "operationId": "getSchema",
+ "description": "Get the database's columns and the latest change sequence.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The schema.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Schema"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "summary": "Add columns",
+ "operationId": "addColumns",
+ "description": "Add one or more columns. A database can have at most 100 columns and 60 indexed columns. A new column cannot be `required` when the database already has rows; add it optional, backfill, then set `required`.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "columns"
+ ],
+ "properties": {
+ "columns": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/components/schemas/ColumnInput"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "The full column list, including the new ids.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ColumnList"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "422": {
+ "description": "Validation failed. `fields` maps each column id or query key to a reason.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ValidationError"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/databases/{projectId}/{databaseId}/col/{columnId}": {
+ "patch": {
+ "summary": "Update column",
+ "operationId": "updateColumn",
+ "description": "Rename, reorder, toggle `indexed` or `required`, or change `options`. Renames never touch rows. `required` can only be turned on when every row has a value.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ },
+ {
+ "$ref": "#/components/parameters/columnId"
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/UpdateColumn"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "The updated column.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Column"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "422": {
+ "description": "Validation failed. `fields` maps each column id or query key to a reason.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ValidationError"
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "summary": "Delete column",
+ "operationId": "deleteColumn",
+ "description": "Delete a column and remove its value from every row.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ },
+ {
+ "$ref": "#/components/parameters/columnId"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The remaining columns.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ColumnList"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/databases/{projectId}/{databaseId}/rows": {
+ "get": {
+ "summary": "List rows",
+ "operationId": "listRows",
+ "description": "List rows with optional equality filters, a sort, and cursor pagination. Filter with `where[]=`; for `multi_select` columns the filter matches rows whose array contains the value. Cursors are stable under concurrent writes.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ },
+ {
+ "name": "sort",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ },
+ "description": "`` or `:desc`. Defaults to newest first. `json` and `multi_select` columns cannot be sorted."
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "schema": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 200,
+ "default": 50
+ }
+ },
+ {
+ "name": "cursor",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ },
+ "description": "The `nextCursor` from the previous page."
+ },
+ {
+ "name": "where[columnId]",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ },
+ "description": "Equality filter. Replace `columnId` with a real column id and repeat for several columns."
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "A page of rows.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/RowPage"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "422": {
+ "description": "Validation failed. `fields` maps each column id or query key to a reason.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ValidationError"
+ }
+ }
+ }
+ }
+ }
+ },
+ "put": {
+ "summary": "Bulk upsert rows",
+ "operationId": "upsertRows",
+ "description": "Create or update up to 500 rows in one atomic call. An entry whose `id` matches an existing row is merged into it; any other entry becomes a new row with that id, or a generated one. If any entry fails validation, nothing is written.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "rows"
+ ],
+ "properties": {
+ "rows": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 500,
+ "items": {
+ "$ref": "#/components/schemas/UpsertRow"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "The written rows and counts.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "rows",
+ "created",
+ "updated"
+ ],
+ "properties": {
+ "rows": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Row"
+ }
+ },
+ "created": {
+ "type": "integer"
+ },
+ "updated": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "413": {
+ "description": "A row exceeds 2 MB of JSON.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "422": {
+ "description": "Validation failed. `fields` maps each column id or query key to a reason.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ValidationError"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/databases/{projectId}/{databaseId}/row": {
+ "post": {
+ "summary": "Create row",
+ "operationId": "createRow",
+ "description": "Create a row. Values are keyed by column id and validated against each column's type. Missing required columns and unknown column ids are rejected.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/RowInput"
+ }
+ }
+ }
+ },
+ "responses": {
+ "201": {
+ "description": "The row, with `rev` 1.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Row"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "413": {
+ "description": "The row exceeds 2 MB of JSON.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "422": {
+ "description": "Validation failed. `fields` maps each column id or query key to a reason.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ValidationError"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/databases/{projectId}/{databaseId}/row/{rowId}": {
+ "get": {
+ "summary": "Get row",
+ "operationId": "getRow",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ },
+ {
+ "$ref": "#/components/parameters/rowId"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Row"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ },
+ "patch": {
+ "summary": "Update row",
+ "operationId": "updateRow",
+ "description": "Merge `columns` into the row and increment `rev`. Set a column to `null` to clear it. Send `If-Match` with the `rev` you last read to make the write conditional.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ },
+ {
+ "$ref": "#/components/parameters/rowId"
+ },
+ {
+ "$ref": "#/components/parameters/ifMatch"
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/RowInput"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "The updated row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Row"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "409": {
+ "description": "`If-Match` did not match the current `rev`. `currentRev` is included.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/StaleRevisionError"
+ }
+ }
+ }
+ },
+ "413": {
+ "description": "The row exceeds 2 MB of JSON.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "422": {
+ "description": "Validation failed. `fields` maps each column id or query key to a reason.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ValidationError"
+ }
+ }
+ }
+ }
+ }
+ },
+ "delete": {
+ "summary": "Delete row",
+ "operationId": "deleteRow",
+ "description": "Delete a row. Send `If-Match` to refuse the delete if the row changed since you read it.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ },
+ {
+ "$ref": "#/components/parameters/rowId"
+ },
+ {
+ "$ref": "#/components/parameters/ifMatch"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Deleted.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "deleted": {
+ "type": "string",
+ "format": "uuid"
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "409": {
+ "description": "`If-Match` did not match the current `rev`.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/StaleRevisionError"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/databases/{projectId}/{databaseId}/changes": {
+ "get": {
+ "summary": "Get changes",
+ "operationId": "getChanges",
+ "description": "Read the change log after a sequence number, up to 500 changes. For a live stream, see the `events` endpoint on the live updates page.",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/projectId"
+ },
+ {
+ "$ref": "#/components/parameters/databaseId"
+ },
+ {
+ "name": "since",
+ "in": "query",
+ "schema": {
+ "type": "integer",
+ "minimum": 0,
+ "default": 0
+ },
+ "description": "Return changes with `seq` greater than this."
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Changes after `since`.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ChangeBatch"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Authentication failed, or Databases is not enabled for this project.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "Unknown project, database, column, or row.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Error"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "securitySchemes": {
+ "bearerAuth": {
+ "type": "http",
+ "scheme": "bearer",
+ "description": "The Authorization header expects a Bearer token. Use an admin API key. This is a server-side secret key. Generate one on the [API keys page](https://app.mintlify.com/settings/organization/api-keys) in your dashboard."
+ }
+ },
+ "parameters": {
+ "projectId": {
+ "name": "projectId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ },
+ "description": "Your project ID, from the API keys page in the dashboard."
+ },
+ "databaseId": {
+ "name": "databaseId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "description": "The database `id`."
+ },
+ "columnId": {
+ "name": "columnId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "pattern": "^col_[a-z0-9]{8}$"
+ },
+ "description": "The column `id`."
+ },
+ "rowId": {
+ "name": "rowId",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "description": "The row `id`."
+ },
+ "ifMatch": {
+ "name": "If-Match",
+ "in": "header",
+ "required": false,
+ "schema": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "description": "The `rev` you last read. The write is refused with `409` if the row has changed since."
+ }
+ },
+ "schemas": {
+ "ColumnType": {
+ "type": "string",
+ "enum": [
+ "text",
+ "number",
+ "boolean",
+ "date",
+ "select",
+ "multi_select",
+ "url",
+ "email",
+ "json"
+ ]
+ },
+ "Column": {
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "type",
+ "position",
+ "indexed",
+ "required"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "example": "col_ua6ithuj"
+ },
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "$ref": "#/components/schemas/ColumnType"
+ },
+ "position": {
+ "type": "integer"
+ },
+ "indexed": {
+ "type": "boolean"
+ },
+ "required": {
+ "type": "boolean"
+ },
+ "options": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Allowed values. Present for `select` and `multi_select` columns."
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updatedAt": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ },
+ "ColumnInput": {
+ "type": "object",
+ "required": [
+ "name",
+ "type"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "type": {
+ "$ref": "#/components/schemas/ColumnType"
+ },
+ "indexed": {
+ "type": "boolean",
+ "description": "Index for filtering and sorting. Not allowed for `multi_select` or `json`."
+ },
+ "required": {
+ "type": "boolean",
+ "description": "Every row must have a value. Not allowed when the database already has rows."
+ },
+ "options": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Allowed values. Required for `select` and `multi_select`."
+ }
+ }
+ },
+ "UpdateColumn": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120
+ },
+ "indexed": {
+ "type": "boolean"
+ },
+ "required": {
+ "type": "boolean"
+ },
+ "options": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "position": {
+ "type": "integer",
+ "minimum": 0,
+ "description": "New index in the column order. Other columns shift to keep positions contiguous."
+ }
+ }
+ },
+ "ColumnList": {
+ "type": "object",
+ "required": [
+ "columns"
+ ],
+ "properties": {
+ "columns": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Column"
+ }
+ }
+ }
+ },
+ "Schema": {
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "columns",
+ "latestSeq"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "name": {
+ "type": "string"
+ },
+ "columns": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Column"
+ }
+ },
+ "latestSeq": {
+ "type": "integer",
+ "description": "Sequence number of the most recent change."
+ }
+ }
+ },
+ "Database": {
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "slug",
+ "status",
+ "createdBy",
+ "createdAt",
+ "updatedAt"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "name": {
+ "type": "string"
+ },
+ "slug": {
+ "type": "string",
+ "example": "apps"
+ },
+ "status": {
+ "type": "string",
+ "enum": [
+ "initializing",
+ "ready"
+ ]
+ },
+ "createdBy": {
+ "type": "string",
+ "description": "The user email or `key:` that created the database."
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updatedAt": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ },
+ "CreateDatabase": {
+ "type": "object",
+ "required": [
+ "name"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 120,
+ "example": "Apps"
+ },
+ "slug": {
+ "type": "string",
+ "pattern": "^[a-z0-9][a-z0-9_-]{0,62}$",
+ "description": "Derived from the name when omitted."
+ }
+ }
+ },
+ "ColumnValues": {
+ "type": "object",
+ "additionalProperties": true,
+ "description": "Values keyed by column id.",
+ "example": {
+ "col_ua6ithuj": "Alpha",
+ "col_8f2k1a0p": 4200
+ }
+ },
+ "RowInput": {
+ "type": "object",
+ "required": [
+ "columns"
+ ],
+ "properties": {
+ "columns": {
+ "$ref": "#/components/schemas/ColumnValues"
+ }
+ }
+ },
+ "UpsertRow": {
+ "type": "object",
+ "required": [
+ "columns"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "description": "Merge into this row if it exists, otherwise create it with this id."
+ },
+ "columns": {
+ "$ref": "#/components/schemas/ColumnValues"
+ }
+ }
+ },
+ "Row": {
+ "type": "object",
+ "required": [
+ "id",
+ "rev",
+ "columns",
+ "createdAt",
+ "updatedAt",
+ "createdBy",
+ "updatedBy"
+ ],
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "rev": {
+ "type": "integer",
+ "description": "Increments on every update. Use with `If-Match`."
+ },
+ "columns": {
+ "$ref": "#/components/schemas/ColumnValues"
+ },
+ "createdAt": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "updatedAt": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "createdBy": {
+ "type": "string"
+ },
+ "updatedBy": {
+ "type": "string"
+ }
+ }
+ },
+ "RowPage": {
+ "type": "object",
+ "required": [
+ "rows",
+ "nextCursor"
+ ],
+ "properties": {
+ "rows": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Row"
+ }
+ },
+ "nextCursor": {
+ "type": "string",
+ "nullable": true,
+ "description": "Pass as `cursor` for the next page. `null` on the last page."
+ }
+ }
+ },
+ "Change": {
+ "type": "object",
+ "required": [
+ "seq",
+ "kind",
+ "actor",
+ "at"
+ ],
+ "properties": {
+ "seq": {
+ "type": "integer"
+ },
+ "kind": {
+ "type": "string",
+ "enum": [
+ "database.updated",
+ "column.added",
+ "column.updated",
+ "column.deleted",
+ "row.created",
+ "row.updated",
+ "row.deleted"
+ ]
+ },
+ "rowId": {
+ "type": "string",
+ "nullable": true
+ },
+ "columnId": {
+ "type": "string",
+ "nullable": true
+ },
+ "rev": {
+ "type": "integer",
+ "nullable": true
+ },
+ "actor": {
+ "type": "string"
+ },
+ "at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ },
+ "ChangeBatch": {
+ "type": "object",
+ "required": [
+ "epoch",
+ "changes",
+ "latestSeq",
+ "oldestSeq"
+ ],
+ "properties": {
+ "epoch": {
+ "type": "string",
+ "format": "uuid",
+ "description": "Identifies this incarnation of the log. Changes when the database is deleted and recreated."
+ },
+ "changes": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Change"
+ }
+ },
+ "latestSeq": {
+ "type": "integer"
+ },
+ "oldestSeq": {
+ "type": "integer",
+ "description": "Oldest retained sequence. The log keeps the most recent 10,000 changes."
+ }
+ }
+ },
+ "Error": {
+ "type": "object",
+ "required": [
+ "error",
+ "code"
+ ],
+ "properties": {
+ "error": {
+ "type": "string"
+ },
+ "code": {
+ "type": "string",
+ "enum": [
+ "bad_request",
+ "unauthorized",
+ "not_found",
+ "conflict",
+ "stale_revision",
+ "too_large",
+ "invalid",
+ "limit",
+ "upstream"
+ ]
+ }
+ }
+ },
+ "ValidationError": {
+ "type": "object",
+ "required": [
+ "error",
+ "code"
+ ],
+ "properties": {
+ "error": {
+ "type": "string"
+ },
+ "code": {
+ "type": "string",
+ "enum": [
+ "invalid",
+ "limit"
+ ]
+ },
+ "fields": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "example": {
+ "col_8f2k1a0p": "expected a number",
+ "col_zzzzzzzz": "unknown column"
+ }
+ },
+ "current": {
+ "type": "integer"
+ },
+ "limit": {
+ "type": "integer"
+ }
+ }
+ },
+ "StaleRevisionError": {
+ "type": "object",
+ "required": [
+ "error",
+ "code",
+ "currentRev"
+ ],
+ "properties": {
+ "error": {
+ "type": "string"
+ },
+ "code": {
+ "type": "string",
+ "enum": [
+ "stale_revision"
+ ]
+ },
+ "currentRev": {
+ "type": "integer"
+ },
+ "ifMatch": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/databases/api.mdx b/databases/api.mdx
new file mode 100644
index 0000000000..e190378f85
--- /dev/null
+++ b/databases/api.mdx
@@ -0,0 +1,80 @@
+---
+title: "Databases REST API"
+sidebarTitle: "REST API"
+description: "Create databases, manage columns, and read and write rows with the Mintlify REST API from a pipeline, a partner portal, or any server-side script."
+keywords: ["databases", "REST API", "rows", "columns", "bulk upsert", "If-Match", "cursor"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
+
+Use the Databases API to keep a database current from wherever the data lives: a release pipeline, a partner portal, a spreadsheet export.
+
+## Authentication
+
+Authenticate with your admin API key. Generate one on the [API keys page](https://app.mintlify.com/settings/organization/api-keys) in your dashboard. Admin API keys begin with `mint_` and are server-side secrets. Do not expose them in client-side code.
+
+Copy your project ID from the same page and use it as the `projectId` path parameter. All endpoints are under `https://api.mintlify.com/v1/databases/{projectId}`.
+
+Writes are attributed to the API key. Rows show `createdBy` and `updatedBy` as `key:`.
+
+## Endpoints
+
+Databases
+
+- [List databases](/api/databases/list-databases)
+- [Create database](/api/databases/create-database)
+- [Get database](/api/databases/get-database)
+- [Delete database](/api/databases/delete-database)
+
+Columns
+
+- [Get schema](/api/databases/get-schema)
+- [Add columns](/api/databases/add-columns)
+- [Update column](/api/databases/update-column)
+- [Delete column](/api/databases/delete-column)
+
+Rows
+
+- [List rows](/api/databases/list-rows): filter with `where[columnId]`, sort, and page with a cursor.
+- [Bulk upsert rows](/api/databases/upsert-rows): up to 500 rows per call, atomic.
+- [Create row](/api/databases/create-row)
+- [Get row](/api/databases/get-row)
+- [Update row](/api/databases/update-row): conditional with `If-Match`.
+- [Delete row](/api/databases/delete-row)
+
+Changes
+
+- [Get changes](/api/databases/get-changes): read the change log in batches.
+- [Live updates](/databases/live-updates): subscribe to the same events over server-sent events.
+
+## Ids, not names
+
+Rows are keyed by column id, such as `col_ua6ithuj`, not by column name. Read the ids once from [Get schema](/api/databases/get-schema) and keep them in your integration. Renaming a column in the dashboard then changes nothing for your code.
+
+## Errors
+
+Every error is JSON with a stable `code`.
+
+| Status | `code` | Meaning |
+| --- | --- | --- |
+| `400` | `bad_request` | Malformed JSON, a bad `If-Match`, or a missing header. |
+| `401` | | Missing or invalid API key, or Databases is not enabled for the project. |
+| `404` | `not_found` | Unknown database, column, or row. |
+| `409` | `conflict` | Slug already in use on this project. |
+| `409` | `stale_revision` | `If-Match` did not match the current `rev`. Includes `currentRev`. |
+| `413` | `too_large` | Row over 2 MB of JSON. |
+| `422` | `invalid` | Validation failed. `fields` maps each column id or query key to a reason. |
+| `422` | `limit` | A limit would be exceeded. Includes `current` and `limit`. |
+
+```json
+{
+ "error": "some values are invalid",
+ "code": "invalid",
+ "fields": {
+ "col_8f2k1a0p": "expected a number",
+ "col_zzzzzzzz": "unknown column"
+ }
+}
+```
diff --git a/databases/columns.mdx b/databases/columns.mdx
new file mode 100644
index 0000000000..84cef64eb3
--- /dev/null
+++ b/databases/columns.mdx
@@ -0,0 +1,50 @@
+---
+title: "Column types"
+description: "The column types a Mintlify database supports, how each validates values, and what indexed and required mean."
+keywords: ["databases", "columns", "column types", "schema", "indexed", "required"]
+---
+
+Every column has a stable id, a display name, a type, and two flags. Values are validated against the type on every write.
+
+## Types
+
+| Type | Accepts | Stored as | Filter and sort |
+| --- | --- | --- | --- |
+| `text` | Any string. | String. | Yes |
+| `number` | A finite number, or a numeric string such as `"42"`. | Number. | Yes |
+| `boolean` | `true`, `false`, or the strings `"true"` and `"false"`. | Boolean. | Yes |
+| `date` | An ISO 8601 date or date-time that exists on the calendar. | ISO 8601 UTC string. | Yes |
+| `select` | One of the column's `options`. | String. | Yes |
+| `multi_select` | An array of the column's `options`. | Array of strings. | Filter by membership; no sort. |
+| `url` | An absolute `http` or `https` URL. Other schemes are rejected. | String. | Yes |
+| `email` | An email address. | String. | Yes |
+| `json` | Any JSON value. | As given. | No |
+
+Dates are normalized to UTC. `2026-09-15` is stored as `2026-09-15T00:00:00.000Z`. A date that does not exist, such as `2026-02-30`, is rejected rather than rolled over.
+
+`select` and `multi_select` columns must declare `options` when created. Values outside the options are rejected with the list of allowed values.
+
+## Flags
+
+### Required
+
+A required column must have a non-null value on every row. Two rules keep existing rows valid:
+
+- You cannot add a new column as required to a database that already has rows. Add it optional, backfill, then set `required`.
+- You cannot set `required` on an existing column while any row lacks a value. The error tells you how many rows are missing one.
+
+### Indexed
+
+An indexed column is faster to filter and sort on. Mark the columns you use in `where` and `sort` as indexed. A database can have up to 60 indexed columns. `multi_select` and `json` columns cannot be indexed.
+
+## Renaming and reordering
+
+Rows are keyed by column id, so renaming a column changes only the schema. Reordering with `position` renumbers the other columns so positions stay unique and contiguous.
+
+## Deleting a column
+
+Deleting a column removes its values from every row. There is no undo.
+
+
+ Deleting a column is destructive. Export the rows first if you might need the values later.
+
diff --git a/databases/component.mdx b/databases/component.mdx
new file mode 100644
index 0000000000..221670e812
--- /dev/null
+++ b/databases/component.mdx
@@ -0,0 +1,86 @@
+---
+title: "Database component"
+sidebarTitle: ""
+description: "Render a Mintlify database as a table on any page, filter and sort it, and generate a page for every row."
+keywords: ["databases", "Database component", "table", "row pages", "MDX"]
+---
+
+
+ The rendering components ship after the API and dashboard. Their shape is documented here so you can plan pages; check back for availability.
+
+
+Use `` to render a database on a page. The component reads the schema for headers and types, and the rows for content, so a page stays current without a redeploy.
+
+```mdx
+
+```
+
+## Props
+
+
+ The database slug.
+
+
+ Column names to show, in order. Defaults to every column in schema order.
+
+
+ Equality filters keyed by column name, for example `{{ status: "published" }}`.
+
+
+ `name` or `name:desc`. Defaults to newest first.
+
+
+ Rows per page, up to 200. Pagination controls appear when there are more.
+
+
+ Show a search box that filters the visible rows.
+
+
+```mdx catalog/apps.mdx
+
+```
+
+Columns render by type: dates in the reader's locale, URLs as links, booleans as checks, `select` values as badges.
+
+## A page for every row
+
+Put a template in the database's folder using the row page convention and every row gets its own URL.
+
+```mdx catalog/apps/[app].mdx
+---
+title: "{{ row.app }} {{ row.version }}"
+---
+
+{{ row.status }}
+
+Downloads: {{ row.downloads }}
+```
+
+Values are available as `row.`. The bracketed segment in the file name chooses the column that becomes the URL slug, so this template produces `/catalog/apps/alpha`, `/catalog/apps/beta`, and so on.
+
+## Reading rows in snippets
+
+For layouts the component does not cover, read rows directly in a [snippet](/create/reusable-snippets) with the `mint.db` helper.
+
+```mdx snippets/top-apps.mdx
+export const TopApps = async () => {
+ const { rows } = await mint.db("apps").find({
+ where: { status: "published" },
+ sort: "downloads:desc",
+ limit: 5,
+ });
+ return (
+
+ {rows.map((row) => - {row.app}
)}
+
+ );
+};
+```
+
+`find`, `get`, and `count` are read-only. Writes go through the [REST API](/databases/api) or the dashboard.
diff --git a/databases/live-updates.mdx b/databases/live-updates.mdx
new file mode 100644
index 0000000000..d2b6c4e024
--- /dev/null
+++ b/databases/live-updates.mdx
@@ -0,0 +1,64 @@
+---
+title: "Live updates"
+description: "Subscribe to a database's change stream over server-sent events and resume where you left off after a disconnect."
+keywords: ["databases", "SSE", "server-sent events", "change stream", "live updates", "realtime"]
+---
+
+Every write to a database appends an event to its change log. Subscribe to the log to keep a portal, a dashboard, or a cache current without polling.
+
+## Subscribe
+
+```bash
+GET /v1/databases/{projectId}/{databaseId}/events
+Accept: text/event-stream
+```
+
+```bash curl
+curl -N "https://api.mintlify.com/v1/databases/$PROJECT_ID/$DATABASE_ID/events" \
+ -H "Authorization: Bearer $MINT_API_KEY"
+```
+
+The stream opens with a `ready` event, replays anything after your position, then pushes each change as it happens.
+
+```text
+event: ready
+data: {"epoch":"6e306bde-6324-4853-9188-ad08415d8a2f","latestSeq":12}
+
+id: 6e306bde-6324-4853-9188-ad08415d8a2f:13
+event: change
+data: {"seq":13,"kind":"row.updated","rowId":"502e5c75-…","columnId":null,"rev":3,"actor":"key:key_2f8a","at":"2026-09-16T07:01:12.108Z"}
+
+: heartbeat
+```
+
+## Events
+
+| `event` | When |
+| --- | --- |
+| `ready` | The stream is open. `data` has the current `epoch` and `latestSeq`. |
+| `change` | A mutation happened. `id` is `epoch:seq`. |
+| `reset` | Your position is no longer valid, usually because the database was deleted and recreated. Discard local state and refetch; the stream then replays from the start. |
+| `reconnect` | The stream is closing on purpose. Reconnect with the `since` value in `data`. |
+| `error` | The database is gone or you lost access. |
+
+`change.kind` is one of `database.updated`, `column.added`, `column.updated`, `column.deleted`, `row.created`, `row.updated`, `row.deleted`.
+
+## Resuming
+
+Streams close after five minutes. Reconnect with the id of the last event you processed, either as the `Last-Event-ID` header, which browsers' `EventSource` sends automatically, or as `?since=`.
+
+```bash
+GET /v1/databases/{projectId}/{databaseId}/events?since=6e306bde-6324-4853-9188-ad08415d8a2f:13
+```
+
+Ids carry an epoch so a stale position from before a wipe-and-recreate cannot be mistaken for a valid one. If your position does not belong to the current epoch, or is ahead of the current log, you receive `reset` followed by a full replay. Always resume with the full `epoch:seq` id: a bare sequence number has no epoch to check, so the stream treats it as unknown and replays from the start.
+
+The log retains the most recent 10,000 changes. A position older than that also triggers `reset`.
+
+## Read the log without streaming
+
+```bash
+GET /v1/databases/{projectId}/{databaseId}/changes?since=12
+```
+
+Returns `{ "epoch", "changes": [...], "latestSeq", "oldestSeq" }` with up to 500 changes after `since`. Useful for batch jobs that reconcile on a schedule.
diff --git a/databases/overview.mdx b/databases/overview.mdx
new file mode 100644
index 0000000000..cdd833d32f
--- /dev/null
+++ b/databases/overview.mdx
@@ -0,0 +1,52 @@
+---
+title: "Databases"
+description: "Store structured content such as app catalogs, release tables, or partner listings as typed tables that Mintlify hosts, and render it on your docs pages."
+keywords: ["databases", "structured content", "tables", "rows", "columns", "catalog"]
+---
+
+
+ Databases are in early access. Access is enabled per project. Contact your Mintlify account team to turn it on.
+
+
+Use Databases to keep structured content out of Git and in a typed table that your team, your partners, and your build pipelines can write to through one API. Each database has a schema of columns and a set of rows. Mintlify hosts the data, keeps a revision on every row, and streams changes to anything that is listening.
+
+Databases fit content that changes on a different cadence than your prose: an app catalog with hundreds of entries maintained by external publishers, a release table that CI updates on every tag, a partner directory that a sales team edits from the dashboard.
+
+## How it works
+
+A database belongs to one project. It has:
+
+- **Columns.** Each column has a name, a type, and optional flags such as `required` and `indexed`. Columns have stable ids, so renaming a column never touches a row.
+- **Rows.** Each row is a JSON object keyed by column id, plus a revision number, timestamps, and the actor who created and last updated it.
+- **A change log.** Every mutation appends an event you can read back or subscribe to over a live stream.
+
+You manage the schema and the rows in the dashboard or through the [REST API](/databases/api). You render rows on a page with the [`` component](/databases/component).
+
+## What you can do
+
+
+
+ Create a database, add columns and rows, and render them on a page.
+
+
+ Text, number, boolean, date, select, multi-select, URL, email, and JSON.
+
+
+ Create databases, manage columns, and read and write rows from CI or a partner portal.
+
+
+ Subscribe to a change stream and react to edits as they happen.
+
+
+
+## Limits
+
+| Limit | Value |
+| --- | --- |
+| Columns per database | 100 |
+| Indexed columns per database | 60 |
+| Row size | 2 MB of JSON |
+| Rows per bulk upsert call | 500 |
+| Rows per page when listing | 200 |
+
+These limits apply on write, so a request that would exceed one returns an error and changes nothing.
diff --git a/databases/quickstart.mdx b/databases/quickstart.mdx
new file mode 100644
index 0000000000..aa620832f9
--- /dev/null
+++ b/databases/quickstart.mdx
@@ -0,0 +1,121 @@
+---
+title: "Databases quickstart"
+sidebarTitle: "Quickstart"
+description: "Create your first database, define its columns, add rows from the dashboard and the API, and render them on a docs page."
+keywords: ["databases", "quickstart", "create database", "add rows"]
+---
+
+
+ Databases are in early access and must be enabled for your project. Contact your Mintlify account team to turn it on.
+
+
+This quickstart builds a small app catalog: a `Apps` database with a name, a version, a status, and a download count, rendered as a table on a docs page.
+
+## Prerequisites
+
+- A project with Databases enabled.
+- An [admin API key](https://app.mintlify.com/settings/organization/api-keys) if you want to write rows from a script. Admin API keys begin with `mint_` and are server-side secrets.
+
+
+
+ In your dashboard, open **Databases** for the project and select **Create**. Give it a name such as `Apps`.
+
+ The slug is derived from the name, `apps` here. You use the slug when you render the database on a page.
+
+
+ ```bash curl
+ curl -X POST https://api.mintlify.com/v1/databases/$PROJECT_ID \
+ -H "Authorization: Bearer $MINT_API_KEY" \
+ -H "Content-Type: application/json" \
+ -d '{ "name": "Apps" }'
+ ```
+ ```json Response
+ {
+ "id": "0b50b639-bff9-43d2-8e62-b3bd93e9a41c",
+ "name": "Apps",
+ "slug": "apps",
+ "status": "ready",
+ "createdBy": "you@example.com",
+ "createdAt": "2026-09-16T06:52:05.737Z",
+ "updatedAt": "2026-09-16T06:52:05.737Z"
+ }
+ ```
+
+
+
+
+ Add the columns your rows need. Mark the ones you filter or sort on as **indexed**, and the ones every row must have as **required**.
+
+
+ ```bash curl
+ curl -X POST https://api.mintlify.com/v1/databases/$PROJECT_ID/$DATABASE_ID/col \
+ -H "Authorization: Bearer $MINT_API_KEY" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "columns": [
+ { "name": "app", "type": "text", "required": true, "indexed": true },
+ { "name": "version", "type": "text" },
+ { "name": "status", "type": "select", "options": ["draft", "published"], "indexed": true },
+ { "name": "downloads", "type": "number" }
+ ]
+ }'
+ ```
+ ```json Response
+ {
+ "columns": [
+ { "id": "col_ua6ithuj", "name": "app", "type": "text", "position": 0, "indexed": true, "required": true },
+ { "id": "col_nzdoc64z", "name": "version", "type": "text", "position": 1, "indexed": false, "required": false },
+ { "id": "col_qtxj9tuf", "name": "status", "type": "select", "position": 2, "indexed": true, "required": false, "options": ["draft", "published"] },
+ { "id": "col_8f2k1a0p", "name": "downloads", "type": "number", "position": 3, "indexed": false, "required": false }
+ ]
+ }
+ ```
+
+
+ Note the column ids. Rows are keyed by id, not by name, so you can rename `downloads` to `installs` later without touching a single row.
+
+
+
+ Add rows in the dashboard grid, or send them from a script. Values are keyed by column id.
+
+ ```bash curl
+ curl -X POST https://api.mintlify.com/v1/databases/$PROJECT_ID/$DATABASE_ID/row \
+ -H "Authorization: Bearer $MINT_API_KEY" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "columns": {
+ "col_ua6ithuj": "Alpha",
+ "col_nzdoc64z": "1.2.0",
+ "col_qtxj9tuf": "published",
+ "col_8f2k1a0p": 4200
+ }
+ }'
+ ```
+
+ Loading many rows at once? Use [bulk upsert](/api/databases/upsert-rows) with up to 500 rows per call.
+
+
+ Every write is validated against the schema. A wrong type, an unknown column id, or a missing required value returns `422` with one reason per column and writes nothing.
+
+
+
+
+ Add the component to any MDX page. It reads the schema for headers and the rows for content.
+
+ ```mdx catalog/apps.mdx
+ ---
+ title: "App catalog"
+ ---
+
+
+ ```
+
+ See [``](/databases/component) for column selection, filtering, and per-row pages.
+
+
+
+## Next steps
+
+- Read about each [column type](/databases/columns) and how values are validated.
+- Wire your release pipeline to the [REST API](/databases/api).
+- Keep a portal or dashboard current with [live updates](/databases/live-updates).