API Reference
Complete Iceberg REST Catalog API documentation.
Table of contents
- Base URL
- Authentication
- Configuration
- Namespaces
- Tables
- Views
- Transactions
- Metrics
- Search
- Credentials
- Health & Metrics
- Error Responses
- Rate Limiting
- Pagination
- Request Headers
- 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 returns400 Bad Request. Omit the field or set it tofalse.
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:
- Table metadata is loaded to determine the storage location
- Table is removed from the catalog registry
- 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
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
- Getting Started - Quick setup
- Authentication - API keys and JWT
- Authorization - Cedar policies