API Reference

Complete Iceberg REST Catalog API documentation.

Table of contents

  1. Base URL
  2. Authentication
  3. Configuration
    1. Get Configuration
  4. Namespaces
    1. List Namespaces
    2. Create Namespace
    3. Get Namespace
    4. Update Namespace Properties
    5. Drop Namespace
  5. Tables
    1. List Tables
    2. Create Table
    3. Load Table
    4. Update Table (Commit)
    5. Table Exists
    6. Drop Table
    7. Rename Table
    8. Register Table
  6. Views
    1. List Views
    2. Create View
    3. Load View
    4. Drop View
    5. View Exists
    6. Commit View
    7. Rename View
  7. Transactions
    1. Commit Transaction
  8. Metrics
    1. Report Metrics
  9. Search
    1. Search Catalog
  10. Credentials
    1. Load Credentials
  11. Health & Metrics
    1. Health Check
    2. Readiness Check
    3. Prometheus Metrics
  12. Error Responses
    1. Error Format
    2. Error Codes
  13. Rate Limiting
  14. Pagination
  15. Request Headers
  16. Next Steps

Base URL

https://your-rustberg-host:8181

Authentication

All endpoints require authentication via Authorization header:

Authorization: Bearer rustberg_your_api_key_here

Or JWT token:

Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

Configuration

Get Configuration

Returns catalog configuration and defaults.

GET /v1/config

Response:

{
  "defaults": {},
  "overrides": {}
}

Namespaces

List Namespaces

GET /v1/namespaces

Query Parameters:

Parameter Type Description
parent string Parent namespace (optional)
pageToken string Pagination token
pageSize integer Results per page (default: 100)

Response:

{
  "namespaces": [
    ["analytics"],
    ["raw", "events"]
  ],
  "next-page-token": "abc123"
}

Create Namespace

POST /v1/namespaces

Request:

{
  "namespace": ["analytics"],
  "properties": {
    "owner": "data-team"
  }
}

Response: 200 OK

{
  "namespace": ["analytics"],
  "properties": {
    "owner": "data-team"
  }
}

Get Namespace

GET /v1/namespaces/{namespace}

Response:

{
  "namespace": ["analytics"],
  "properties": {
    "owner": "data-team"
  }
}

Update Namespace Properties

POST /v1/namespaces/{namespace}/properties

Request:

{
  "updates": {
    "description": "Analytics tables"
  },
  "removals": ["deprecated-key"]
}

Drop Namespace

DELETE /v1/namespaces/{namespace}

Response: 204 No Content


Tables

List Tables

GET /v1/namespaces/{namespace}/tables

Response:

{
  "identifiers": [
    {
      "namespace": ["analytics"],
      "name": "events"
    },
    {
      "namespace": ["analytics"],
      "name": "users"
    }
  ]
}

Create Table

POST /v1/namespaces/{namespace}/tables

Request:

{
  "name": "events",
  "location": "s3://my-bucket/analytics/events",
  "schema": {
    "type": "struct",
    "schema-id": 0,
    "fields": [
      {
        "id": 1,
        "name": "id",
        "required": true,
        "type": "long"
      },
      {
        "id": 2,
        "name": "event_type",
        "required": true,
        "type": "string"
      },
      {
        "id": 3,
        "name": "timestamp",
        "required": true,
        "type": "timestamptz"
      }
    ]
  },
  "partition-spec": {
    "spec-id": 0,
    "fields": [
      {
        "source-id": 3,
        "field-id": 1000,
        "name": "ts_day",
        "transform": "day"
      }
    ]
  },
  "properties": {
    "write.format.default": "parquet"
  }
}

Response: 200 OK with table metadata

Staged table creation (stage-create: true) is not supported. If sent, the server returns 400 Bad Request. Omit the field or set it to false.

Load Table

GET /v1/namespaces/{namespace}/tables/{table}

Response:

{
  "metadata-location": "s3://bucket/metadata/v1.metadata.json",
  "metadata": {
    "format-version": 2,
    "table-uuid": "abc123",
    "location": "s3://bucket/table",
    "schema": {...},
    "partition-spec": {...},
    "properties": {...}
  },
  "config": {
    "s3.access-key-id": "AKIA...",
    "s3.secret-access-key": "..."
  }
}

Update Table (Commit)

POST /v1/namespaces/{namespace}/tables/{table}

Request:

{
  "identifier": {
    "namespace": ["analytics"],
    "name": "events"
  },
  "requirements": [
    {
      "type": "assert-current-schema-id",
      "current-schema-id": 0
    }
  ],
  "updates": [
    {
      "action": "add-schema",
      "schema": {
        "type": "struct",
        "fields": [...]
      }
    },
    {
      "action": "set-current-schema",
      "schema-id": 1
    }
  ]
}

Table Exists

HEAD /v1/namespaces/{namespace}/tables/{table}

Response: 204 No Content (exists) or 404 Not Found

Drop Table

DELETE /v1/namespaces/{namespace}/tables/{table}

Query Parameters:

Parameter Type Default Description
purgeRequested boolean false When true, also delete all underlying data files

Purge Behavior:

When purgeRequested=true:

  1. Table metadata is loaded to determine the storage location
  2. Table is removed from the catalog registry
  3. All files in the table’s location are recursively deleted (data files, manifest files, metadata files)

Example:

# Drop table (keep data files)
curl -X DELETE "$CATALOG_URL/v1/namespaces/analytics/tables/events"

# Drop table and purge all data
curl -X DELETE "$CATALOG_URL/v1/namespaces/analytics/tables/events?purgeRequested=true"

Purge is a destructive operation and cannot be undone. All data files will be permanently deleted from storage.

Response: 204 No Content

Rename Table

POST /v1/tables/rename

Request:

{
  "source": {
    "namespace": ["analytics"],
    "name": "events_old"
  },
  "destination": {
    "namespace": ["analytics"],
    "name": "events_new"
  }
}

Register Table

Register an existing table from a metadata file location.

POST /v1/namespaces/{namespace}/register

Request:

{
  "name": "imported_events",
  "metadata-location": "s3://bucket/metadata/v1.metadata.json"
}

Views

List Views

GET /v1/namespaces/{namespace}/views

Create View

POST /v1/namespaces/{namespace}/views

Load View

GET /v1/namespaces/{namespace}/views/{view}

Drop View

DELETE /v1/namespaces/{namespace}/views/{view}

View Exists

HEAD /v1/namespaces/{namespace}/views/{view}

Commit View

POST /v1/namespaces/{namespace}/views/{view}

Rename View

POST /v1/views/rename

Transactions

Commit Transaction

Commit changes to multiple tables atomically.

Multi-table transactions are atomic. All table changes are applied together or none are. The implementation uses optimistic concurrency control with version tracking and WriteBatch for atomic registry updates. On conflict, the operation is automatically retried with exponential backoff.

POST /v1/transactions/commit

Request:

{
  "table-changes": [
    {
      "identifier": {
        "namespace": ["analytics"],
        "name": "events"
      },
      "requirements": [...],
      "updates": [...]
    },
    {
      "identifier": {
        "namespace": ["analytics"],
        "name": "events_summary"
      },
      "requirements": [...],
      "updates": [...]
    }
  ]
}

Response: 204 No Content on success

Atomicity Guarantee:

  • All requirements validated across all tables BEFORE any changes
  • All metadata files written (orphan files are safe)
  • All registry entries updated atomically via WriteBatch
  • Automatic retry with exponential backoff on conflicts (up to 10 retries)

On Failure:

  • HTTP 409 for commit conflicts (after max retries exhausted)
  • HTTP 500 for other failures
  • Error message indicates all-or-nothing semantics
  • No partial commits - either all tables are updated or none are

Metrics

Report Metrics

Report table operation metrics from clients.

POST /v1/namespaces/{namespace}/tables/{table}/metrics

Request:

{
  "table-name": "analytics.events",
  "snapshot-id": 1234567890,
  "filter": "timestamp > '2026-01-01'",
  "schema-id": 0,
  "projected-field-ids": [1, 2, 3],
  "projected-field-names": ["id", "event_type", "timestamp"],
  "metrics": {
    "total-planning-duration": {"unit": "nanos", "value": 123456},
    "total-data-manifests": {"unit": "count", "value": 5},
    "total-files-size": {"unit": "bytes", "value": 1073741824}
  }
}

Search Catalog

Search for tables and views across namespaces.

GET /v1/search

Query Parameters:

Parameter Type Description
query string Search query
type string table or view (optional)

Response:

{
  "results": [
    {
      "type": "table",
      "identifier": {
        "namespace": ["analytics"],
        "name": "events"
      }
    }
  ]
}

Credentials

Load Credentials

Get temporary credentials for accessing table storage.

GET /v1/namespaces/{namespace}/tables/{table}/credentials

Response:

{
  "s3.access-key-id": "ASIATEMP...",
  "s3.secret-access-key": "...",
  "s3.session-token": "...",
  "expiration-ms": 3600000
}

Health & Metrics

Health Check

GET /health

Response: 200 OK

{
  "status": "healthy"
}

Readiness Check

GET /ready

Response: 200 OK when ready to serve traffic

Prometheus Metrics

GET /metrics

Response: Prometheus text format

# HELP rustberg_requests_total Total HTTP requests
# TYPE rustberg_requests_total counter
rustberg_requests_total{method="GET",status="200"} 1234

Error Responses

Error Format

{
  "error": {
    "message": "Table not found",
    "type": "NoSuchTableException",
    "code": 404
  }
}

Error Codes

Code Type Description
400 BadRequestException Invalid request format
401 NotAuthenticatedException Missing/invalid auth
403 NotAuthorizedException Insufficient permissions
404 NoSuchNamespaceException Namespace not found
404 NoSuchTableException Table not found
409 AlreadyExistsException Resource already exists
409 CommitFailedException Optimistic concurrency failure
422 ValidationException Business rule violation
429 TooManyRequestsException Rate limited
500 ServiceException Internal error

Rate Limiting

When rate limited, response includes:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1706313600

Pagination

List endpoints support cursor-based pagination:

GET /v1/namespaces?pageSize=50&pageToken=abc123

Response:

{
  "namespaces": [...],
  "next-page-token": "def456"
}

When next-page-token is null or absent, no more results.


Request Headers

Header Required Description
Authorization Yes Bearer token
Content-Type Yes (POST) application/json
X-Request-Id No Request correlation ID
X-Iceberg-Access-Delegation No vended-credentials

Next Steps