The Observe REST API serves a read-only subset of the Apache Iceberg REST Catalog protocol under the v1/iceberg/catalog endpoint.
Base URL
The base URL is:
https://<your-tenant>.observeinc.com/v1/iceberg/catalogYour Iceberg REST client appends the spec's own /v1, so on the wire requests look like …/v1/iceberg/catalog/v1/config. The warehouse prefix is observe and the namespace is iceberg (both returned by the config endpoint); your client discovers these automatically.
Authentication
Use your existing Observe API token as the standard two-part bearer credential:
Authorization: Bearer <your-customer-id> <token-secret>
This is the same token you use for the Observe REST API — there is no separate catalog credential. Token lifetime and rotation follow your normal Observe API token settings.
Endpoints
All endpoints are read-only (GET / HEAD).
https://<customer_id>.observeinc.com/v1/iceberg/catalog| Method | Path (after the base URL) | Purpose |
|---|---|---|
| GET | /v1/config | Bootstrap: returns the warehouse prefix and the list of supported endpoints |
| GET | /v1/observe/namespaces | List namespaces (returns iceberg) |
| GET | /v1/observe/namespaces/iceberg | Get a namespace |
| HEAD | /v1/observe/namespaces/iceberg | Namespace existence check |
| GET | /v1/observe/namespaces/iceberg/tables | List tables in the namespace |
| GET | /v1/observe/namespaces/iceberg/tables/{table} | Load a table's metadata (schema, current snapshot, data-file locations) |
| HEAD | /v1/observe/namespaces/iceberg/tables/{table} | Table existence check |
Any write/mutation, the OAuth token-exchange endpoint, scan planning, views, or any other path returns 403 — they are not part of this read-only catalog.
Examples
Config
GET /v1/iceberg/catalog/v1/config
Authorization: Bearer <your-customer-id> <token>
200 OK
{"defaults":{},"overrides":{"prefix":"observe"},"endpoints":[
"GET /v1/{prefix}/namespaces",
"GET /v1/{prefix}/namespaces/{namespace}",
"HEAD /v1/{prefix}/namespaces/{namespace}",
"GET /v1/{prefix}/namespaces/{namespace}/tables",
"GET /v1/{prefix}/namespaces/{namespace}/tables/{table}",
"HEAD /v1/{prefix}/namespaces/{namespace}/tables/{table}"]}
List namespaces
GET /v1/iceberg/catalog/v1/observe/namespaces
Authorization: Bearer <your-customer-id> <token>
200 OK
{"namespaces":[["iceberg"]],"next-page-token":null}
List tables
GET /v1/iceberg/catalog/v1/observe/namespaces/iceberg/tables
Authorization: Bearer <your-customer-id> <token>
200 OK
{"identifiers":[
{"namespace":["iceberg"],"name":"42578362"},
{"namespace":["iceberg"],"name":"42586667"}],
"next-page-token":null}
Load table
GET /v1/iceberg/catalog/v1/observe/namespaces/iceberg/tables/<table>
Authorization: Bearer <your-customer-id> <token>
200 OK
{
"metadata-location": "s3://<your-bucket>/.../metadata/<n>.metadata.json",
"metadata": { ...full Iceberg table metadata document... },
"config": { "client.region": "us-west-2" }
}
The response contains only the table's metadata location, the metadata document, and the storage region. No storage credentials are returned — your engine reads the data files directly from your bucket using its own AWS credentials. See Data ownership and security.
Troubleshooting
The following table describes some common error messages you might see, and what each error means:
| Status | Meaning |
|---|---|
400 BadRequestException | Wrong warehouse prefix, or an unsupported X-Iceberg-* request header was sent.For example, see Connect DuckDB. |
401 NotAuthorizedException | Missing or invalid Observe API token. Check the token and retry. |
403 ForbiddenException | Either the path/method isn't part of the read-only catalog surface, such as writes or OAuth token exchange, or your principal lacks catalog-access permission. |
404 NoSuchNamespaceException / NoSuchTableException | The requested namespace or table does not exist. |
404 NotFoundException | Catalog access is not enabled for your tenant. Contact your Observe representative. |