# Catalog over HTTP

[Read this page in HTML](https://www.scopedb.io/docs/api-reference/catalog)

Use the Catalog API to read and manage database, schema, table, and view definitions. Reads return complete definitions. Writes replace the selected resource, so the safe editing sequence is read, edit, preview, apply, and read back.

For a terminal workflow that exports definitions and saves reviewable plans, use the [CLI Catalog guide](https://www.scopedb.io/docs/guides/scopedb-cli/catalog.md).

## Resources

Set `SCOPEDB_ENDPOINT` and `SCOPEDB_API_KEY` from the [shared setup](https://www.scopedb.io/docs/api-reference.md#base-url-and-authentication). Resource names in paths are percent-encoded individually.

| Resource | Path                                                               | Methods                |
| -------- | ------------------------------------------------------------------ | ---------------------- |
| Catalog  | `/v1/catalog`                                                      | `GET`, `PUT`           |
| Database | `/v1/catalog/databases/{database}`                                 | `GET`, `PUT`, `DELETE` |
| Schema   | `/v1/catalog/databases/{database}/schemas/{schema}`                | `GET`, `PUT`, `DELETE` |
| Table    | `/v1/catalog/databases/{database}/schemas/{schema}/tables/{table}` | `GET`, `PUT`, `DELETE` |
| View     | `/v1/catalog/databases/{database}/schemas/{schema}/views/{view}`   | `GET`, `PUT`, `DELETE` |

`GET` returns the definition as the JSON response body, with its version in the `ETag` header. Reads are not paginated. Prefer the narrowest resource you need: read one table for its schema, or one schema to discover its tables and views.

`PUT` creates or replaces a resource using a complete JSON definition. Omitted fields and children are cleared; this is not a partial update. `DELETE` removes the selected resource. Mutation responses contain `before`, `after`, and `destructive`, with an `ETag` response header. A missing resource is represented by null in `before` or `after`.

## Read a table definition

This example uses the `events` table from the [quickstart](https://www.scopedb.io/docs/guides/quickstart.md#1-create-an-event-table), in the `scopedb` database and `public` schema. It requires curl and, for the edit below, [jq](https://jqlang.org/).

```bash
export SCOPEDB_TABLE_URL="$SCOPEDB_ENDPOINT/v1/catalog/databases/scopedb/schemas/public/tables/events"

curl --fail-with-body --silent --show-error \
  "$SCOPEDB_TABLE_URL" \
  -H "Authorization: Bearer $SCOPEDB_API_KEY" \
  --dump-header catalog.headers \
  --output table.json
```

Inspect `table.json`. The definition includes the table's `name` and `columns`, whose entries include `name` and `data_type`, along with its other settings. Preserve all fields, including fields your client does not recognize, when editing an existing definition.

A column with an `expression` is a read-only [computed column](https://www.scopedb.io/docs/reference/computed-columns.md). Edit that field in the complete table definition to change the expression for historical and incoming rows.

## Preview a change

Change only the comment and keep the ETag, including its quotes:

```bash
jq '.comment = "Checkout events"' table.json > desired-table.json
catalog_etag=$(awk 'tolower($1) == "etag:" {gsub("\r", ""); print $2}' catalog.headers)
test -n "$catalog_etag" && \
curl --fail-with-body --silent --show-error -X PUT \
  "$SCOPEDB_TABLE_URL?dry_run=true" \
  -H "Authorization: Bearer $SCOPEDB_API_KEY" \
  -H "Content-Type: application/json" \
  -H "If-Match: $catalog_etag" \
  --data-binary @desired-table.json \
  --dump-header plan.headers \
  --output plan.json
```

Read `plan.json` and compare `before` with `after`. This comment-only change should have `destructive: false`. `dry_run=true` previews the change without committing it.

## Apply the reviewed definition

After reviewing the plan, send the same `desired-table.json` with the preview's ETag and without `dry_run=true`:

```bash
plan_etag=$(awk 'tolower($1) == "etag:" {gsub("\r", ""); print $2}' plan.headers)
test -n "$plan_etag" && \
curl --fail-with-body --silent --show-error -X PUT \
  "$SCOPEDB_TABLE_URL" \
  -H "Authorization: Bearer $SCOPEDB_API_KEY" \
  -H "Content-Type: application/json" \
  -H "If-Match: $plan_etag" \
  --data-binary @desired-table.json
```

The response's `after` definition contains the new comment. Read the table again to verify the stored value:

```bash
curl --fail-with-body --silent --show-error \
  "$SCOPEDB_TABLE_URL" \
  -H "Authorization: Bearer $SCOPEDB_API_KEY"
```

## Handle conflicts and interrupted writes

| Control or response                      | Meaning                                                                                                      |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `If-Match: <etag>`                       | Apply only against the catalog version you reviewed. Keep the value unchanged, including its quotes.         |
| HTTP `412`, `catalog_version_mismatch`   | The catalog changed. Read the current definition and preview a new plan; do not bypass the check.            |
| HTTP `409`, `catalog_destructive_change` | The change can remove data or definitions. Inspect the preview before explicitly allowing it.                |
| `allow_destructive=true`                 | Permit a destructive mutation. This is an explicit opt-in on `PUT` or `DELETE`, separate from `dry_run`.     |
| `catalog_commit_outcome_unknown`         | A commit may have completed. Read the resource to establish its current state before planning another write. |

Both query flags accept `true` or `false` and default to false. A dry run can show a destructive plan without committing it. Do not apply such a plan until you understand what it removes.

Treat an interrupted mutation as potentially committed. Never automatically replay a Catalog write just because the connection timed out. A dry run does not commit, but its ETag may become stale before application. See [HTTP errors and retries](https://www.scopedb.io/docs/api-reference.md#errors-and-retries).

## Related contents

* [API reference](https://www.scopedb.io/docs/api-reference.md)

* [Append rows over HTTP](https://www.scopedb.io/docs/api-reference/append.md)

* [ScopeDB CLI](https://www.scopedb.io/docs/guides/scopedb-cli.md)
