---
title: "HeliosDB-Lite Branch REST API Specification"
---

# HeliosDB-Lite Branch REST API Specification

**Created**: 2025-12-01

---

## Overview

This document specifies the RESTful API for managing database branches in HeliosDB-Lite. The API enables creating, managing, and working with data across branches via HTTP.

---

## Base URL

```
Production: https://api.heliosdb.local/v1
Development: http://localhost:8080/v1
```

---

## Authentication

All endpoints require authentication via one of:

### Bearer Token (JWT)
```http
Authorization: Bearer <jwt_token>
```

### API Key
```http
X-API-Key: <api_key>
```

---

## Common Response Formats

### Success Response
```json
{
  "success": true,
  "data": { ... },
  "meta": {
    "request_id": "req_abc123",
    "execution_time_ms": 45
  }
}
```

### Error Response
```json
{
  "success": false,
  "error": {
    "code": "BRANCH_NOT_FOUND",
    "message": "Branch 'feature-xyz' does not exist",
    "details": { ... }
  },
  "meta": {
    "request_id": "req_abc123"
  }
}
```

---

## Error Codes

| Code | HTTP State | Description |
|------|-------------|-------------|
| `BRANCH_NOT_FOUND` | 404 | Branch does not exist |
| `BRANCH_EXISTS` | 409 | Branch name already in use |
| `BRANCH_PROTECTED` | 403 | Cannot modify protected branch |
| `MERGE_CONFLICT` | 409 | Unresolved merge conflicts |
| `INVALID_SQL` | 400 | SQL syntax error |
| `UNAUTHORIZED` | 401 | Invalid or missing auth |
| `FORBIDDEN` | 403 | Insufficient permissions |
| `RATE_LIMITED` | 429 | Too many requests |
| `INTERNAL_ERROR` | 500 | Server error |

---

## Endpoints

### Branch Management

#### List All Branches
```http
GET /v1/branches
```

**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `status` | string | `all` | Filter: `active`, `merged`, `deleted`, `all` |
| `page` | integer | 1 | Page number |
| `limit` | integer | 20 | Results per page (max 100) |
| `sort` | string | `created_at` | Sort field: `name`, `created_at`, `updated_at` |
| `order` | string | `desc` | Sort order: `asc`, `desc` |

**Response:**
```json
{
  "success": true,
  "data": {
    "branches": [
      {
        "id": "br_main_001",
        "name": "main",
        "display_name": "Main Branch",
        "status": "active",
        "is_default": true,
        "is_protected": true,
        "created_at": "2025-01-01T00:00:00Z",
        "updated_at": "2025-12-01T10:00:00Z",
        "stats": {
          "tables": 15,
          "rows": 125000,
          "size_bytes": 52428800
        }
      },
      {
        "id": "br_feat_abc123",
        "name": "feature-auth",
        "display_name": "Authentication Feature",
        "status": "active",
        "is_default": false,
        "is_protected": false,
        "source_branch": "main",
        "source_snapshot": "snap_xyz789",
        "created_at": "2025-12-01T08:00:00Z",
        "updated_at": "2025-12-01T09:30:00Z",
        "stats": {
          "tables": 15,
          "rows": 125050,
          "size_bytes": 52430000,
          "changes_from_source": 50
        }
      }
    ],
    "pagination": {
      "page": 1,
      "limit": 20,
      "total": 2,
      "total_pages": 1
    }
  }
}
```

---

#### Create Branch
```http
POST /v1/branches
```

**Request Body:**
```json
{
  "name": "feature-auth",
  "display_name": "Authentication Feature",
  "source_branch": "main",
  "as_of": {
    "type": "timestamp",
    "value": "2025-12-01T08:00:00Z"
  },
  "metadata": {
    "owner": "alice@example.com",
    "ticket": "JIRA-1234",
    "description": "Implementing OAuth2 authentication"
  }
}
```

**As-Of Options:**
```json
// Current state
{ "type": "now" }

// Specific timestamp
{ "type": "timestamp", "value": "2025-12-01T08:00:00Z" }

// After specific transaction
{ "type": "transaction", "value": 12345 }

// Specific SCN (System Change Number)
{ "type": "scn", "value": 987654 }

// Specific snapshot
{ "type": "snapshot", "value": "snap_xyz789" }
```

**Response:**
```json
{
  "success": true,
  "data": {
    "id": "br_feat_abc123",
    "name": "feature-auth",
    "display_name": "Authentication Feature",
    "status": "active",
    "source_branch": "main",
    "source_snapshot": "snap_xyz789",
    "created_at": "2025-12-01T10:00:00Z"
  }
}
```

---

#### Get Branch Details
```http
GET /v1/branches/{branch_name}
```

**Path Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `branch_name` | string | Branch name or ID |

**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `include_stats` | boolean | true | Include statistics |
| `include_history` | boolean | false | Include recent history |

**Response:**
```json
{
  "success": true,
  "data": {
    "id": "br_feat_abc123",
    "name": "feature-auth",
    "display_name": "Authentication Feature",
    "status": "active",
    "is_default": false,
    "is_protected": false,
    "source_branch": "main",
    "source_snapshot": "snap_xyz789",
    "created_at": "2025-12-01T08:00:00Z",
    "updated_at": "2025-12-01T09:30:00Z",
    "metadata": {
      "owner": "alice@example.com",
      "ticket": "JIRA-1234",
      "description": "Implementing OAuth2 authentication"
    },
    "stats": {
      "tables": 15,
      "rows": 125050,
      "size_bytes": 52430000,
      "changes_from_source": 50,
      "inserts": 30,
      "updates": 15,
      "deletes": 5
    },
    "divergence": {
      "source_branch": "main",
      "commits_ahead": 5,
      "commits_behind": 2,
      "can_fast_forward": false
    }
  }
}
```

---

#### Update Branch
```http
PATCH /v1/branches/{branch_name}
```

**Request Body:**
```json
{
  "display_name": "Updated Display Name",
  "is_protected": true,
  "metadata": {
    "owner": "bob@example.com"
  }
}
```

**Response:**
```json
{
  "success": true,
  "data": {
    "id": "br_feat_abc123",
    "name": "feature-auth",
    "display_name": "Updated Display Name",
    "is_protected": true,
    "updated_at": "2025-12-01T11:00:00Z"
  }
}
```

---

#### Delete Branch
```http
DELETE /v1/branches/{branch_name}
```

**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `force` | boolean | false | Force delete even with uncommitted changes |

**Response:**
```json
{
  "success": true,
  "data": {
    "deleted": true,
    "branch_name": "feature-auth",
    "deleted_at": "2025-12-01T12:00:00Z"
  }
}
```

---

#### Merge Branches
```http
POST /v1/branches/{branch_name}/merge
```

**Request Body:**
```json
{
  "target_branch": "main",
  "conflict_resolution": "source_wins",
  "delete_source_after_merge": true,
  "merge_message": "Merge feature-auth into main",
  "dry_run": false
}
```

**Conflict Resolution Options:**
- `source_wins` - Source branch values take precedence
- `target_wins` - Target branch values take precedence
- `manual` - Return conflicts for manual resolution
- `abort` - Fail if any conflicts exist

**Response (Success):**
```json
{
  "success": true,
  "data": {
    "status": "merged",
    "source_branch": "feature-auth",
    "target_branch": "main",
    "merge_commit": "mc_def456",
    "changes_merged": 50,
    "conflicts_resolved": 3,
    "source_deleted": true,
    "merged_at": "2025-12-01T13:00:00Z"
  }
}
```

**Response (Conflicts):**
```json
{
  "success": false,
  "error": {
    "code": "MERGE_CONFLICT",
    "message": "Merge has conflicts requiring resolution",
    "details": {
      "conflicts": [
        {
          "table": "users",
          "row_id": "123",
          "column": "email",
          "source_value": "alice@new.com",
          "target_value": "alice@old.com",
          "conflict_type": "update_update"
        }
      ]
    }
  }
}
```

---

### Data Operations

#### List Tables in Branch
```http
GET /v1/branches/{branch_name}/tables
```

**Response:**
```json
{
  "success": true,
  "data": {
    "tables": [
      {
        "name": "users",
        "schema": "public",
        "row_count": 10000,
        "columns": [
          {"name": "id", "type": "INTEGER", "nullable": false, "primary_key": true},
          {"name": "name", "type": "TEXT", "nullable": false},
          {"name": "email", "type": "TEXT", "nullable": false},
          {"name": "created_at", "type": "TIMESTAMP", "nullable": false}
        ],
        "indexes": ["idx_users_email"],
        "created_at": "2025-01-01T00:00:00Z"
      }
    ]
  }
}
```

---

#### Query Table Data
```http
GET /v1/branches/{branch_name}/tables/{table_name}/data
```

**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `columns` | string | `*` | Comma-separated column names |
| `filter` | string | - | WHERE clause (URL encoded) |
| `order_by` | string | - | ORDER BY clause |
| `page` | integer | 1 | Page number |
| `limit` | integer | 100 | Rows per page (max 1000) |
| `as_of_type` | string | `now` | Time-travel type |
| `as_of_value` | string | - | Time-travel value |

**Example:**
```http
GET /v1/branches/main/tables/users/data?columns=id,name,email&filter=active%3Dtrue&limit=50
```

**Response:**
```json
{
  "success": true,
  "data": {
    "columns": ["id", "name", "email"],
    "rows": [
      [1, "Alice", "alice@example.com"],
      [2, "Bob", "bob@example.com"]
    ],
    "pagination": {
      "page": 1,
      "limit": 50,
      "total": 2,
      "total_pages": 1
    }
  }
}
```

---

#### Insert Data
```http
POST /v1/branches/{branch_name}/tables/{table_name}/data
```

**Request Body:**
```json
{
  "rows": [
    {"name": "Charlie", "email": "charlie@example.com"},
    {"name": "Diana", "email": "diana@example.com"}
  ],
  "on_conflict": "error"
}
```

**On Conflict Options:**
- `error` - Return error on conflict
- `ignore` - Skip conflicting rows
- `update` - Update existing rows

**Response:**
```json
{
  "success": true,
  "data": {
    "inserted": 2,
    "ids": [3, 4]
  }
}
```

---

#### Update Data
```http
PUT /v1/branches/{branch_name}/tables/{table_name}/data
```

**Request Body:**
```json
{
  "filter": "id = 1",
  "updates": {
    "email": "alice@newdomain.com",
    "updated_at": "2025-12-01T14:00:00Z"
  }
}
```

**Response:**
```json
{
  "success": true,
  "data": {
    "updated": 1
  }
}
```

---

#### Delete Data
```http
DELETE /v1/branches/{branch_name}/tables/{table_name}/data
```

**Query Parameters:**
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `filter` | string | Yes | WHERE clause (required for safety) |

**Response:**
```json
{
  "success": true,
  "data": {
    "deleted": 5
  }
}
```

---

### SQL Operations

#### Execute Query (Read-Only)
```http
POST /v1/branches/{branch_name}/query
```

**Request Body:**
```json
{
  "sql": "SELECT u.name, COUNT(o.id) as order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.name ORDER BY order_count DESC LIMIT 10",
  "params": [],
  "as_of": {
    "type": "timestamp",
    "value": "2025-12-01T08:00:00Z"
  },
  "timeout_ms": 30000
}
```

**Response:**
```json
{
  "success": true,
  "data": {
    "columns": ["name", "order_count"],
    "column_types": ["TEXT", "BIGINT"],
    "rows": [
      ["Alice", 150],
      ["Bob", 120],
      ["Charlie", 95]
    ],
    "row_count": 3,
    "execution_plan": "...",
    "execution_time_ms": 45
  }
}
```

---

#### Execute Statement (DDL/DML)
```http
POST /v1/branches/{branch_name}/execute
```

**Request Body:**
```json
{
  "sql": "CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT NOT NULL, price DECIMAL(10,2))",
  "params": [],
  "timeout_ms": 30000
}
```

**Response:**
```json
{
  "success": true,
  "data": {
    "statement_type": "CREATE_TABLE",
    "affected_rows": 0,
    "execution_time_ms": 12
  }
}
```

---

### Time-Travel Operations

#### Get Branch History
```http
GET /v1/branches/{branch_name}/history
```

**Query Parameters:**
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `from` | string | - | Start timestamp |
| `to` | string | - | End timestamp |
| `limit` | integer | 50 | Max results |

**Response:**
```json
{
  "success": true,
  "data": {
    "history": [
      {
        "id": "tx_001",
        "type": "transaction",
        "timestamp": "2025-12-01T10:00:00Z",
        "scn": 1000,
        "summary": "INSERT INTO users (5 rows)",
        "user": "alice@example.com"
      },
      {
        "id": "snap_001",
        "type": "snapshot",
        "timestamp": "2025-12-01T09:00:00Z",
        "scn": 900,
        "summary": "Automatic snapshot",
        "size_bytes": 52428800
      }
    ]
  }
}
```

---

#### List Snapshots
```http
GET /v1/branches/{branch_name}/snapshots
```

**Response:**
```json
{
  "success": true,
  "data": {
    "snapshots": [
      {
        "id": "snap_xyz789",
        "timestamp": "2025-12-01T09:00:00Z",
        "scn": 900,
        "type": "automatic",
        "size_bytes": 52428800,
        "tables": 15,
        "rows": 125000
      }
    ]
  }
}
```

---

#### Restore to Snapshot
```http
POST /v1/branches/{branch_name}/restore/{snapshot_id}
```

**Request Body:**
```json
{
  "create_backup_branch": true,
  "backup_branch_name": "backup-before-restore"
}
```

**Response:**
```json
{
  "success": true,
  "data": {
    "restored": true,
    "snapshot_id": "snap_xyz789",
    "restored_to_scn": 900,
    "backup_branch": "backup-before-restore"
  }
}
```

---

## Rate Limiting

| Endpoint Category | Rate Limit |
|-------------------|------------|
| Read operations | 1000/minute |
| Write operations | 100/minute |
| Query execution | 60/minute |
| Branch creation | 10/minute |

Rate limit headers:
```http
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 950
X-RateLimit-Reset: 1701432060
```

---

## Webhooks (Future)

Branch events can trigger webhooks:

```json
{
  "event": "branch.created",
  "timestamp": "2025-12-01T10:00:00Z",
  "data": {
    "branch_id": "br_feat_abc123",
    "branch_name": "feature-auth",
    "source_branch": "main"
  }
}
```

Events:
- `branch.created`
- `branch.deleted`
- `branch.merged`
- `branch.protected`
- `branch.data_changed`

---

## Client Access

Call the API from any HTTP client (the `curl` examples above show each request), or
generate a client from the OpenAPI specification below.

---

## OpenAPI Specification

Full OpenAPI 3.0 specification available at:
- `/v1/openapi.json`
- `/v1/openapi.yaml`

Interactive documentation at:
- `/v1/docs` (Swagger UI)
- `/v1/redoc` (ReDoc)

---

