# Alter a table: move it (`catalog`, `schema`), rename it (`name`), change

`POST /datanotes/operations/alter_table/` (operation `alter_table`)

Alter a table: move it (`catalog`, `schema`), rename it (`name`), change
`partition` / `filename` patterns, `description` (changes, never goes: "" is refused), `aliases`,
`exclude` folders, `row_template`
("" removes it), `history` (true | false | "default"), `autolink_target`
(true | false | "default": may automatic links link its rows? default: yes, unless its rows are named by
a date or a time) or `tags` (key/value
labels merged into the table's, e.g. `{"domain": "health"}`; a `null` value removes that tag;
`clear_tags: true` removes every tag first, so with `tags` the table keeps exactly those),
`archive` (folder name inside the table folder) or `fields` (untyped fields, name → default; a
`null` value removes one). Rows, archive and transaction log follow; links are updated; renamed
rows keep their old name in `aliases`. A change of metadata only (tags, description, aliases,
history, autolink_target, row_template, fields) rewrites the table entry alone: no row is moved or rewritten. Refused
when a row cannot fill a pattern. Renaming or moving the table is refused while a CHECK that follows
links, or a `ref_where` / `ref_by`, of another table reads it through a link (link targets are not
rewritten): the conflicts name them. Use `dry_run` to see `planned_moves`; undo with undo_migration.

The schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `X-Datanotes-Actor` | header | `string` | no | JSON: on whose behalf the write is made, recorded in the journal (`harness`, `model`, `session`). |

## Request body

`application/json`, required

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `table` | `string` | yes |  |  |
| `catalog` | `string \| null` | no | `null` |  |
| `schema` | `string \| null` | no | `null` |  |
| `name` | `string \| null` | no | `null` |  |
| `partition` | `string \| null` | no | `null` |  |
| `filename` | `string \| null` | no | `null` |  |
| `description` | `string \| null` | no | `null` | The new description: what a row records (it changes, never goes: "" is refused). |
| `aliases` | `string[] \| null` | no | `null` |  |
| `history` | `boolean \| "default" \| null` | no | `null` | Keep the table's versions: true, false, or "default" (the database's setting). |
| `autolink_target` | `boolean \| "default" \| null` | no | `null` | May automatic links link the table's rows? true, false, or "default" (yes, unless its rows are named by a date or a time). |
| `exclude` | `string[] \| null` | no | `null` |  |
| `row_template` | `string \| null` | no | `null` | Markdown body of new rows; "" removes it. |
| `tags` | `object \| null` | no | `null` | Tags to add or change (strings); a null value removes that tag. The other tags are kept. |
| `clear_tags` | `boolean` | no | `false` | Remove every tag first (with `tags`: the table keeps exactly those). |
| `archive` | `string \| null` | no | `null` | Archive folder: a folder name inside the table folder (e.g. "_archive"); "" = the database default (`archive_folder`). Archived rows follow. |
| `fields` | `object \| null` | no | `null` | Untyped fields to set (name → default, as in create_table `fields`); a null value removes that field. The other fields are kept; a name cannot be a column. |
| `dry_run` | `boolean` | no | `false` |  |

## Responses

| Status | Description | Body |
| --- | --- | --- |
| 200 | Done. | `OpResult` (application/json) |
| 400 | Bad input: the body is not a JSON object, or an argument is unknown, missing or of the wrong type. | `Error` (application/json) |
| 401 | Missing or wrong bearer token. | `Error` (application/json) |
| 403 | A named token beyond its permissions (the engine's administration, tables outside its `write` patterns, schema changes without `ddl`). | `Error` (application/json) |
| 404 | Unknown table, view, migration, note or folder. | `Error` (application/json) |
| 409 | Ambiguous table name: it matches several tables (`paths` or `tables` lists them). | `AmbiguousName` (application/json) |
| 422 | Refused (validation failures, conflicts, an unmet `expect`): nothing written. Same body as 200, with `ok: false` and the reasons. | `OpResult` (application/json) |
| 500 | Unexpected error (`{error}`), or a write that failed partway and could not be rolled back: `rolled_back: false`, `failed` lists the files left (undo_migration on `migration_id` retries the rollback). | `OpResult \| Error` (application/json) |
| 503 | A write that failed partway (a file another program holds) and was rolled back: `rolled_back: true`, nothing written. Send it again later. Same body as 200, with `ok: false` and `failed`. | `OpResult` (application/json) |

The schemas named here are in [openapi.json](https://datanotes.dev/openapi.json) (`components.schemas`).
