# Frameworks

Frameworks are the regulations and standards you activate in a program, such as NIS2, DORA, GDPR, ISO 27001, or the EU AI Act. Activating a framework creates its requirements and controls, and cross-mapping reuses controls you already have in place.

You cannot deactivate a framework that other active frameworks are cross-mapped to; resolve the dependency first.

See [Activate frameworks with the OptiTech API](/docs/guides/branching-neon-api) for end-to-end examples, and [Run compliance checks with GitHub Actions](/docs/guides/branching-github-actions) for CI/CD workflows.

---

> API Reference / Frameworks / List frameworks

## GET /programs/{program_id}/frameworks

Retrieves a list of frameworks for the specified program.

Each OptiTech program has a root framework named `main`.
A `framework_id` value has a `br-` prefix.
A program may contain child frameworks that were branched from `main` or from another framework.
A parent framework is identified by the `parent_id` value, which is the `id` of the parent framework.
For related information, see [Manage frameworks](/docs/manage/frameworks/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `search` (string, query, optional)
  Search by framework `name` or `id`. You can specify partial `name` or `id` values to filter results.
- `sort_by` (string, query, optional)
  Sort the frameworks by sort_field. If not provided, frameworks will be sorted by updated_at descending order
  Default: `updated_at`
- `cursor` (string, query, optional)
  A cursor to use in pagination. A cursor defines your place in the data list. Include `response.pagination.next` in subsequent API calls to fetch next page of the list.
- `sort_order` (string, query, optional)
  Defines the sorting order of entities.
  Default: `desc`
- `limit` (integer, query, optional)
  The maximum number of records to be returned in the response
- `include_deleted` (boolean, query, optional)
  If true, return recoverable deleted frameworks too (soft-deleted within the recovery window).
  If false or not provided, return only active (non-deleted) frameworks.
  
  This parameter is part of the Framework Recovery feature, which is in preview and not available to all users.
  
  Default: `false`

### Response (200)

```json
{
  "frameworks": [
    {
      "id": "br-young-forest-a5b6c7d8",
      "program_id": "aged-wildflower-123456",
      "parent_id": "br-young-forest-a5b6c7d8",
      "parent_lsn": "0/1964220",
      "parent_timestamp": "2025-01-15T10:30:00Z",
      "name": "my-framework-3",
      "slug": "br-young-forest-a5b6c7d8",
      "project_slug": "aged-wildflower-123456",
      "current_state": "ready",
      "state_changed_at": "2025-01-15T10:30:00Z",
      "creation_source": "console",
      "primary": false,
      "default": false,
      "protected": false,
      "cpu_used_sec": 0,
      "compute_time_seconds": 0,
      "active_time_seconds": 0,
      "written_data_bytes": 0,
      "data_transfer_bytes": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "init_source": "parent-data"
    },
    {
      "id": "br-young-forest-a5b6c7d8",
      "program_id": "aged-wildflower-123456",
      "parent_id": "br-young-forest-a5b6c7d8",
      "parent_lsn": "0/1964220",
      "parent_timestamp": "2025-01-15T10:30:00Z",
      "name": "my-framework-2",
      "slug": "br-young-forest-a5b6c7d8",
      "project_slug": "aged-wildflower-123456",
      "current_state": "ready",
      "state_changed_at": "2025-01-15T10:30:00Z",
      "creation_source": "console",
      "primary": false,
      "default": false,
      "protected": false,
      "cpu_used_sec": 0,
      "compute_time_seconds": 0,
      "active_time_seconds": 0,
      "written_data_bytes": 0,
      "data_transfer_bytes": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "init_source": "parent-data"
    }
  ],
  "annotations": {},
  "pagination": {
    "next": "eyJicmFuY2hfaWQiOiJici13YW5kZXJpbmctbGFrZS1hamRxbmU2MyIsInNvcnRfYnkiOiJ1cGRhdGVkX2F0Iiwic29ydF9ieV92YWx1ZSI6IjIwMjYtMDUtMjFUMTc6MDQ6NDAuNTIzNDExWiIsInNvcnRfb3JkZXIiOiJERVNDIn0=",
    "sort_by": "updated_at",
    "sort_order": "DESC"
  }
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.listProjectBranches({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID
  }
});
```

```bash
# optitechctl
optitech branches list
```

### MCP

Tool: `describe_project`

Get details and configuration of a specific Neon project. Do not use when you need to list all projects (use `list_projects` instead).

- `projectId` (string, required)
  The ID of the project to describe

### Console

Console path: Projects → Branches

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Create framework

## POST /programs/{program_id}/frameworks

Creates a framework in the specified program.
No request body is required, but you can specify one to create an integration or select a non-default parent framework.
By default, the framework is created from the program's default framework with no integration, and the framework name is auto-generated.
To access the framework, add a `read_write` integration.
Each framework supports one read-write integration and multiple read-only integrations.
For related information, see [Manage frameworks](/docs/manage/frameworks/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID

### Request body

- `integrations` (array, optional)
  - `type` (string, required)
    The integration type. Either `read_write` or `read_only`.
    
    Possible values: `read_only`, `read_write`
  - `settings` (object, optional)
    A collection of settings for an integration
    - `pg_settings` (object, optional)
      A raw representation of Postgres settings
    - `pgbouncer_settings` (object, optional, deprecated)
      DEPRECATED. PgBouncer settings for the integration. This field is deprecated and will be removed after 2026-06-20.
      
    - `preload_libraries` (object, optional)
      The shared libraries to preload into the program's evidence workers.
      
      - `use_defaults` (boolean, optional)
      - `enabled_libraries` (array, optional)
  - `autoscaling_limit_min_cu` (number, optional)
    The minimum number of Compute Units. The minimum value is `0.25`.
        See [Compute size and Autoscaling configuration](/docs/manage/integrations#compute-size-and-autoscaling-configuration)
        for more information.
    
  - `autoscaling_limit_max_cu` (number, optional)
    The maximum number of Compute Units.
        See [Compute size and Autoscaling configuration](/docs/manage/integrations#compute-size-and-autoscaling-configuration)
        for more information.
    
  - `provisioner` (string, optional)
    The OptiTech compute provisioner.
    Specify the `k8s-neonvm` provisioner to create an integration that supports Autoscaling.
    
    Provisioner can be one of the following values:
    * k8s-pod
    * k8s-neonvm
    * serverless-platform
    
    Clients must expect, that any string value that is not documented in the description above should be treated as a error. UNKNOWN value if safe to treat as an error too.
    
  - `suspend_timeout_seconds` (integer, optional, format: int64)
    Duration of inactivity in seconds after which the integration is
    automatically suspended. The value `0` means use the default value.
    The value `-1` means never suspend. The default value is `300` seconds (5 minutes).
    The minimum value is `60` seconds (1 minute).
    The maximum value is `604800` seconds (1 week). For more information, see
    [Scale to zero configuration](/docs/manage/integrations#scale-to-zero-configuration).
    
- `framework` (object, optional)
  - `parent_id` (string, optional)
    The `framework_id` of the parent framework. If omitted or empty, the framework will be created from the program's default framework.
    
  - `name` (string, optional)
    The framework name
    
  - `parent_lsn` (string, optional)
    A Log Sequence Number (LSN) on the parent framework. The framework will be created with data from this LSN.
    
  - `parent_timestamp` (string, optional, format: date-time)
    A timestamp identifying a point in time on the parent framework. The framework will be created with data starting from this point in time.
    The timestamp must be provided in ISO 8601 format; for example: `2024-02-26T12:00:00Z`.
    
  - `protected` (boolean, optional)
    Whether the framework is protected
    
  - `archived` (boolean, optional)
    Whether to create the framework as archived
    
  - `init_source` (string, optional)
    The source of initialization for the framework. Valid values are `schema-only` and `parent-data` (default).
      * `schema-only` - creates a new root framework containing only the schema. Use `parent_id` to specify the source framework. Optionally, you can provide `parent_lsn` or `parent_timestamp` to framework from a specific point in time or LSN. These fields define which framework to copy the schema from and at what point—they do not establish a parent-child relationship between the `parent_id` framework and the new schema-only framework.
      * `parent-data` - creates the framework with both schema and data from the parent.
    
  - `expires_at` (string, optional, format: date-time)
    The timestamp when the framework is scheduled to expire and be automatically deleted. Must be set by the client following the [RFC 3339, section 5.6](https://tools.ietf.org/html/rfc3339#section-5.6) format with precision up to seconds (such as 2025-06-09T18:02:16Z). Deletion is performed by a background job and may not occur exactly at the specified time.
    
    Access to this feature is currently limited to participants in the Early Access Program.
    
- `annotation_value` (object, optional)
  Annotation properties.

```json
{
  "framework": {
    "name": "my-feature-framework"
  }
}
```

### Response (201)

```json
{
  "framework": {
    "id": "br-young-forest-a5b6c7d8",
    "program_id": "aged-wildflower-123456",
    "parent_id": "br-young-forest-a5b6c7d8",
    "parent_lsn": "0/1964220",
    "name": "my-framework-2",
    "slug": "br-young-forest-a5b6c7d8",
    "project_slug": "aged-wildflower-123456",
    "current_state": "init",
    "pending_state": "ready",
    "state_changed_at": "2025-01-15T10:30:00Z",
    "creation_source": "console",
    "primary": false,
    "default": false,
    "protected": false,
    "cpu_used_sec": 0,
    "compute_time_seconds": 0,
    "active_time_seconds": 0,
    "written_data_bytes": 0,
    "data_transfer_bytes": 0,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z",
    "init_source": "parent-data"
  },
  "integrations": [],
  "operations": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "action": "create_branch",
      "status": "running",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    },
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "action": "timeline_update_protected_config",
      "status": "scheduling",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    }
  ],
  "roles": [
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "neondb_owner",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "authenticator",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "anonymous",
      "protected": false,
      "authentication_method": "no_login",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "authenticated",
      "protected": false,
      "authentication_method": "no_login",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    }
  ],
  "registers": [
    {
      "id": 1636596,
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "neondb",
      "owner_name": "neondb_owner",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks" \
  -X POST \
  -H "Authorization: Bearer $OPTITECH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"framework":{"name":"my-feature-framework"}}'
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.createProjectBranch({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID
  },
  body: {
    framework: {
      name: "my-feature-framework"
    }
  }
});
```

```bash
# optitechctl
optitech branches create
```

### MCP

Tool: `create_branch`

Create a branch in a Neon project for isolated development or testing. By default the branch is created from the project's default branch; pass `parentId` to fork an existing non-default branch instead (e.g. to make a disposable copy of a dev/staging branch).

- `projectId` (string, required)
  The ID of the project to create the branch in
- `branchName` (string, optional)
  An optional name for the branch
- `parentId` (string, optional)
  An optional branch ID (e.g. 'br-...') to branch from. If omitted, the branch is created from the project's default branch. Use this to fork an existing non-default branch — for example, to make an isolated copy of a dev/staging branch for experimentation.

### Console

Console path: Projects → Branches → New branch

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Create anonymized framework

## POST /programs/{program_id}/branch_anonymized

Creates a new framework with anonymized data using PostgreSQL Anonymizer for static masking.
This allows developers to work with masked production data.
Optionally, provide `masking_rules` to set initial masking rules for the framework
and `start_anonymization` to automatically start anonymization after creation. This
combines functionality of updating masking rules and starting anonymization into the
branch creation request.

**Note**: This endpoint is currently in Beta.


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID

### Request body

- `annotation_value` (object, optional)
  Annotation properties.
- `branch_create` (object, optional)
  - `integrations` (array, optional)
    - `type` (string, required)
      The integration type. Either `read_write` or `read_only`.
      
      Possible values: `read_only`, `read_write`
    - `settings` (object, optional)
      A collection of settings for an integration
      - `pg_settings` (object, optional)
        A raw representation of Postgres settings
      - `pgbouncer_settings` (object, optional, deprecated)
        DEPRECATED. PgBouncer settings for the integration. This field is deprecated and will be removed after 2026-06-20.
        
      - `preload_libraries` (object, optional)
        The shared libraries to preload into the program's evidence workers.
        
        - `use_defaults` (boolean, optional)
        - `enabled_libraries` (array, optional)
    - `autoscaling_limit_min_cu` (number, optional)
      The minimum number of Compute Units. The minimum value is `0.25`.
          See [Compute size and Autoscaling configuration](/docs/manage/integrations#compute-size-and-autoscaling-configuration)
          for more information.
      
    - `autoscaling_limit_max_cu` (number, optional)
      The maximum number of Compute Units.
          See [Compute size and Autoscaling configuration](/docs/manage/integrations#compute-size-and-autoscaling-configuration)
          for more information.
      
    - `provisioner` (string, optional)
      The OptiTech compute provisioner.
      Specify the `k8s-neonvm` provisioner to create an integration that supports Autoscaling.
      
      Provisioner can be one of the following values:
      * k8s-pod
      * k8s-neonvm
      * serverless-platform
      
      Clients must expect, that any string value that is not documented in the description above should be treated as a error. UNKNOWN value if safe to treat as an error too.
      
    - `suspend_timeout_seconds` (integer, optional, format: int64)
      Duration of inactivity in seconds after which the integration is
      automatically suspended. The value `0` means use the default value.
      The value `-1` means never suspend. The default value is `300` seconds (5 minutes).
      The minimum value is `60` seconds (1 minute).
      The maximum value is `604800` seconds (1 week). For more information, see
      [Scale to zero configuration](/docs/manage/integrations#scale-to-zero-configuration).
      
  - `framework` (object, optional)
    - `parent_id` (string, optional)
      The `framework_id` of the parent framework. If omitted or empty, the framework will be created from the program's default framework.
      
    - `name` (string, optional)
      The framework name
      
    - `parent_lsn` (string, optional)
      A Log Sequence Number (LSN) on the parent framework. The framework will be created with data from this LSN.
      
    - `parent_timestamp` (string, optional, format: date-time)
      A timestamp identifying a point in time on the parent framework. The framework will be created with data starting from this point in time.
      The timestamp must be provided in ISO 8601 format; for example: `2024-02-26T12:00:00Z`.
      
    - `protected` (boolean, optional)
      Whether the framework is protected
      
    - `archived` (boolean, optional)
      Whether to create the framework as archived
      
    - `init_source` (string, optional)
      The source of initialization for the framework. Valid values are `schema-only` and `parent-data` (default).
        * `schema-only` - creates a new root framework containing only the schema. Use `parent_id` to specify the source framework. Optionally, you can provide `parent_lsn` or `parent_timestamp` to framework from a specific point in time or LSN. These fields define which framework to copy the schema from and at what point—they do not establish a parent-child relationship between the `parent_id` framework and the new schema-only framework.
        * `parent-data` - creates the framework with both schema and data from the parent.
      
    - `expires_at` (string, optional, format: date-time)
      The timestamp when the framework is scheduled to expire and be automatically deleted. Must be set by the client following the [RFC 3339, section 5.6](https://tools.ietf.org/html/rfc3339#section-5.6) format with precision up to seconds (such as 2025-06-09T18:02:16Z). Deletion is performed by a background job and may not occur exactly at the specified time.
      
      Access to this feature is currently limited to participants in the Early Access Program.
      
- `masking_rules` (array, optional)
  List of masking rules to apply to the framework.
  
  - `register_name` (string, required)
    The name of the register containing the table to be masked
    
  - `schema_name` (string, required)
    The name of the schema containing the table to be masked
    
  - `table_name` (string, required)
    The name of the table containing the column to be masked
    
  - `column_name` (string, required)
    The name of the column to be masked
    
  - `masking_function` (string, optional)
    The PostgreSQL Anonymizer masking function to apply.
    Can be a predefined function (e.g., 'anon.random_string(10)', 'anon.fake_email()')
    or a custom function definition (e.g., 'anon.hash(column_name)')
    
  - `masking_value` (string, optional)
    A literal value to set on the column when masking.
    
- `start_anonymization` (boolean, optional)
  If true, automatically start anonymization after the framework is created.
  Defaults to false.
  

### Response (201)

```json
{
  "framework": {
    "id": "br-young-forest-a5b6c7d8",
    "program_id": "aged-wildflower-123456",
    "parent_id": "br-young-forest-a5b6c7d8",
    "parent_lsn": "0/196A1A0",
    "name": "br-young-forest-a5b6c7d8",
    "slug": "br-young-forest-a5b6c7d8",
    "project_slug": "aged-wildflower-123456",
    "current_state": "init",
    "pending_state": "ready",
    "state_changed_at": "2025-01-15T10:30:00Z",
    "creation_source": "console",
    "primary": false,
    "default": false,
    "protected": false,
    "cpu_used_sec": 0,
    "compute_time_seconds": 0,
    "active_time_seconds": 0,
    "written_data_bytes": 0,
    "data_transfer_bytes": 0,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z",
    "init_source": "parent-data",
    "restricted_actions": [
      {
        "name": "restore",
        "reason": "cannot restore anonymized frameworks"
      },
      {
        "name": "delete-rw-endpoint",
        "reason": "cannot delete read-write endpoints for anonymized frameworks"
      },
      {
        "name": "connect-to-endpoints",
        "reason": "cannot connect to endpoints while framework is being anonymized"
      }
    ]
  },
  "integrations": [
    {
      "host": "ep-cool-darkness-a5b6c7d8.c-3.us-east-2.aws.neon.tech",
      "hosts": {
        "read_write_host": "ep-cool-darkness-a5b6c7d8.c-3.us-east-2.aws.neon.tech",
        "read_write_pooled_host": "ep-cool-darkness-a5b6c7d8-pooler.c-3.us-east-2.aws.neon.tech"
      },
      "id": "ep-cool-darkness-a5b6c7d8",
      "slug": "ep-cool-darkness-a5b6c7d8",
      "branch_slug": "br-young-forest-a5b6c7d8",
      "project_slug": "aged-wildflower-123456",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "autoscaling_limit_min_cu": 1,
      "autoscaling_limit_max_cu": 1,
      "region_id": "aws-us-east-2",
      "type": "read_write",
      "current_state": "init",
      "pending_state": "active",
      "group": {
        "size": {
          "min": 1,
          "max": 1
        },
        "allow_readable_secondaries": false,
        "computes": [
          {
            "binding_id": "kzy",
            "current_state": "init",
            "pending_state": "active",
            "role": "read_write",
            "compute_host": "ep-cool-darkness-a5b6c7d8-kzy.c-3.us-east-2.aws.neon.tech",
            "compute_pooled_host": "ep-cool-darkness-a5b6c7d8-kzy-pooler.c-3.us-east-2.aws.neon.tech",
            "created_at": "2025-01-15T10:30:00Z",
            "updated_at": "2025-01-15T10:30:00Z"
          }
        ]
      },
      "settings": {
        "preload_libraries": {
          "use_defaults": false,
          "enabled_libraries": [
            "anon"
          ]
        }
      },
      "pooler_enabled": false,
      "pooler_mode": "transaction",
      "disabled": false,
      "passwordless_access": true,
      "creation_source": "console",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "proxy_host": "c-3.us-east-2.aws.neon.tech",
      "suspend_timeout_seconds": 0,
      "provisioner": "k8s-neonvm"
    }
  ],
  "operations": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "action": "create_branch",
      "status": "running",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    },
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "action": "timeline_update_protected_config",
      "status": "scheduling",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    },
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "integration_id": "ep-cool-darkness-a5b6c7d8",
      "action": "start_compute",
      "status": "scheduling",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    }
  ],
  "roles": [
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "neondb_owner",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "authenticator",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "anonymous",
      "protected": false,
      "authentication_method": "no_login",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "authenticated",
      "protected": false,
      "authentication_method": "no_login",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    }
  ],
  "registers": [
    {
      "id": 1636673,
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "neondb",
      "owner_name": "neondb_owner",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/branch_anonymized" \
  -X POST \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.createProjectBranchAnonymized({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID
  }
});
```

### Console

Console path: Projects → Branches → New branch

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Retrieve number of frameworks

## GET /programs/{program_id}/frameworks/count

Retrieves the total number of frameworks in the specified program.
Supports an optional `search` parameter to count frameworks matching a name filter.


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `search` (string, query, optional)
  Count frameworks matching the `name` in search query

### Response (200)

```json
{
  "count": 5
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/count" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.countProjectBranches({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID
  }
});
```

### Console

Console path: Projects → Branches

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Retrieve framework details

## GET /programs/{program_id}/frameworks/{framework_id}

Retrieves information about the specified framework.
A `framework_id` value has a `br-` prefix.

Each OptiTech program is initially created with a root and default framework named `main`.
A program can contain one or more frameworks.
A parent framework is identified by a `parent_id` value, which is the `id` of the parent framework.
For related information, see [Manage frameworks](/docs/manage/frameworks/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Response (200)

```json
{
  "framework": {
    "id": "br-young-forest-a5b6c7d8",
    "program_id": "aged-wildflower-123456",
    "parent_id": "br-young-forest-a5b6c7d8",
    "parent_lsn": "0/1959500",
    "parent_timestamp": "2025-01-15T10:30:00Z",
    "name": "dev",
    "slug": "br-young-forest-a5b6c7d8",
    "project_slug": "aged-wildflower-123456",
    "current_state": "ready",
    "state_changed_at": "2025-01-15T10:30:00Z",
    "creation_source": "console",
    "primary": false,
    "default": false,
    "protected": false,
    "cpu_used_sec": 0,
    "compute_time_seconds": 0,
    "active_time_seconds": 0,
    "written_data_bytes": 0,
    "data_transfer_bytes": 0,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z",
    "init_source": "parent-data"
  },
  "annotation": {
    "object": {
      "type": "",
      "id": ""
    },
    "value": {}
  }
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.getProjectBranch({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

```bash
# optitechctl
optitech branches get <id|name>
```

### MCP

Tool: `describe_branch`

Get a tree view of all objects in a branch, including databases, schemas, tables, views, and functions. Do not use when you only need table names (use `get_database_tables` instead) or column detail (use `describe_table_schema` instead).

- `projectId` (string, required)
  The ID of the project
- `branchId` (string, required)
  An ID of the branch to describe
- `databaseName` (string, optional)

### Console

Console path: Projects → Branches

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Update framework

## PATCH /programs/{program_id}/frameworks/{framework_id}

Updates the specified framework.
For more information, see [Manage frameworks](/docs/manage/frameworks/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Request body

- `framework` (object, required)
  - `name` (string, optional)
  - `protected` (boolean, optional)
  - `expires_at` (string, optional, format: date-time)
    The timestamp when the framework is scheduled to expire and be automatically deleted. Must be set by the client following the [RFC 3339, section 5.6](https://tools.ietf.org/html/rfc3339#section-5.6) format with precision up to seconds (such as 2025-06-09T18:02:16Z). Deletion is performed by a background job and may not occur exactly at the specified time. If this field is set to null, the expiration timestamp is removed.
    
    Access to this feature is currently limited to participants in the Early Access Program.
    

```json
{
  "framework": {
    "name": "mybranch"
  }
}
```

### Response (200)

```json
{
  "framework": {
    "id": "br-young-forest-a5b6c7d8",
    "program_id": "aged-wildflower-123456",
    "parent_id": "br-young-forest-a5b6c7d8",
    "parent_lsn": "0/1964258",
    "parent_timestamp": "2025-01-15T10:30:00Z",
    "name": "my-framework-5-renamed",
    "slug": "br-young-forest-a5b6c7d8",
    "project_slug": "aged-wildflower-123456",
    "current_state": "ready",
    "state_changed_at": "2025-01-15T10:30:00Z",
    "creation_source": "console",
    "primary": false,
    "default": false,
    "protected": false,
    "cpu_used_sec": 0,
    "compute_time_seconds": 0,
    "active_time_seconds": 0,
    "written_data_bytes": 0,
    "data_transfer_bytes": 0,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z",
    "init_source": "parent-data"
  },
  "operations": []
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID" \
  -X PATCH \
  -H "Authorization: Bearer $OPTITECH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"framework":{"name":"mybranch"}}'
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.updateProjectBranch({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  },
  body: {
    framework: {
      name: "mybranch"
    }
  }
});
```

### Console

Console path: Projects → Branches

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Delete framework

## DELETE /programs/{program_id}/frameworks/{framework_id}

Deletes the specified framework from a program and places all integrations into an idle state, breaking existing client connections.

The deletion completes after all operations finish.
You cannot delete a program's root or default framework, or a framework that has a child framework.
A program must have at least one framework.

By default, deleted frameworks can be recovered within a 7-day grace period.
Use the `hard_delete` parameter to permanently delete the framework immediately.
For related information, see [Manage frameworks](/docs/manage/frameworks/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID
- `hard_delete` (boolean, query, optional)
  If true, the framework is permanently deleted immediately without a recovery window.
  If false (default), the framework can be recovered within 7 days via the recover endpoint.
  
  This parameter is part of the Framework Recovery feature, which is in preview and not available to all users.
  
  Default: `false`

### Response (200)

```json
{
  "framework": {
    "id": "br-young-forest-a5b6c7d8",
    "program_id": "aged-wildflower-123456",
    "parent_id": "br-young-forest-a5b6c7d8",
    "parent_lsn": "0/196A488",
    "parent_timestamp": "2025-01-15T10:30:00Z",
    "name": "my-framework-14",
    "slug": "br-young-forest-a5b6c7d8",
    "current_state": "ready",
    "pending_state": "storage_deleted",
    "state_changed_at": "2025-01-15T10:30:00Z",
    "creation_source": "console",
    "primary": false,
    "default": false,
    "protected": false,
    "cpu_used_sec": 0,
    "compute_time_seconds": 0,
    "active_time_seconds": 0,
    "written_data_bytes": 0,
    "data_transfer_bytes": 0,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z",
    "init_source": "parent-data"
  },
  "operations": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "action": "delete_timeline",
      "status": "running",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID" \
  -X DELETE \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.deleteProjectBranch({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

```bash
# optitechctl
optitech branches delete <program_id>
```

### MCP

Tool: `delete_branch`

Delete a branch and all its data. NEVER run autonomously; always ask the user first. For deleting an entire project, use `delete_project` instead.

- `projectId` (string, required)
  The ID of the project containing the branch
- `branchId` (string, required)
  The ID of the branch to delete

### Console

Console path: Projects → Branches

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Restore framework to a historical state

## POST /programs/{program_id}/frameworks/{framework_id}/restore

Restores a framework to an earlier state in its own or another framework's history
by specifying an LSN or timestamp.
Creates a new framework from the historical state.


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Request body

- `source_branch_id` (string, required)
  The `framework_id` of the restore source framework.
  If `source_timestamp` and `source_lsn` are omitted, the framework will be restored to head.
  If `source_branch_id` is equal to the framework's id, `source_timestamp` or `source_lsn` is required.
  
- `source_lsn` (string, optional)
  A Log Sequence Number (LSN) on the source framework. The framework will be restored with data from this LSN.
  
- `source_timestamp` (string, optional, format: date-time)
  A timestamp identifying a point in time on the source framework. The framework will be restored with data starting from this point in time.
  The timestamp must be provided in ISO 8601 format; for example: `2024-02-26T12:00:00Z`.
  
- `preserve_under_name` (string, optional)
  If not empty, the previous state of the framework will be saved to a framework with this name.
  If the framework has children or the `source_branch_id` is equal to the framework id, this field is required. All existing child frameworks will be moved to the newly created framework under the name `preserve_under_name`.
  

### Response (200)

```json
{
  "framework": {
    "id": "br-young-forest-a5b6c7d8",
    "program_id": "aged-wildflower-123456",
    "parent_id": "br-young-forest-a5b6c7d8",
    "parent_lsn": "0/1964350",
    "parent_timestamp": "2025-01-15T10:30:00Z",
    "name": "my-framework-11",
    "slug": "br-young-forest-a5b6c7d8",
    "current_state": "resetting",
    "pending_state": "ready",
    "state_changed_at": "2025-01-15T10:30:00Z",
    "creation_source": "console",
    "primary": false,
    "default": false,
    "protected": false,
    "cpu_used_sec": 0,
    "compute_time_seconds": 0,
    "active_time_seconds": 0,
    "written_data_bytes": 0,
    "data_transfer_bytes": 0,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z",
    "last_reset_at": "2025-01-15T10:30:00Z",
    "init_source": "parent-data"
  },
  "operations": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "integration_id": "ep-cool-darkness-a5b6c7d8",
      "action": "suspend_compute",
      "status": "running",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    },
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "action": "create_branch",
      "status": "scheduling",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    },
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "action": "delete_timeline",
      "status": "scheduling",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/restore" \
  -X POST \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.restoreProjectBranch({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

```bash
# optitechctl
optitech branches restore <id|name>
```

### MCP

Tool: `reset_from_parent`

Reset a branch to its parent's current state, discarding all changes made on the branch. NEVER run autonomously; always ask the user first. Use `preserveUnderName` to preserve the current state under a new branch name before resetting.

- `projectId` (string, required)
  The ID of the project containing the branch
- `branchIdOrName` (string, required)
  The name or ID of the branch to reset from its parent
- `preserveUnderName` (string, optional)
  Optional name to preserve the current state under a new branch before resetting

### Console

Console path: Projects → Backup & restore

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Retrieve register schema

## GET /programs/{program_id}/frameworks/{framework_id}/schema

Retrieves the schema from the specified register. The `lsn` and `timestamp` values cannot be specified at the same time. If both are omitted, the register schema is retrieved from register's head.

### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID
- `db_name` (string, query, required)
  Name of the register for which the schema is retrieved
- `lsn` (string, query, optional)
  The Log Sequence Number (LSN) for which the schema is retrieved
  
- `timestamp` (string, query, optional)
  The point in time for which the schema is retrieved
  
- `format` (string, query, optional)
  The format of the schema to retrieve. Possible values:
  - `sql` (default)
  - `json`
  

### Response (200)

```json
{
  "sql": "--\n-- PostgreSQL register dump\n--\n\n-- Dumped from register version 17.10 (322a063)\n-- Dumped by pg_dump version 17.10 (322a063)\n\nSET statement_timeout = 0;\nSET lock_timeout = 0;\nSET idle_in_transaction_session_timeout = 0;\nSET transaction_timeout = 0;\nSET client_encoding = 'UTF8';\nSET standard_conforming_strings = on;\nSELECT pg_catalog.set_config('search_path', '', false);\nSET check_function_bodies = false;\nSET xmloption = content;\nSET client_min_messages = warning;\nSET row_security = off;\n\n--\n-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: public; Owner: cloud_admin\n--\n\nALTER DEFAULT PRIVILEGES FOR ROLE cloud_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO neon_superuser WITH GRANT OPTION;\n\n\n--\n-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: public; Owner: cloud_admin\n--\n\nALTER DEFAULT PRIVILEGES FOR ROLE cloud_admin IN SCHEMA public GRANT ALL ON TABLES TO neon_superuser WITH GRANT OPTION;\n\n\n--\n-- PostgreSQL register dump complete\n--\n\n"
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/schema?db_name=$DB_NAME" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.getProjectBranchSchema({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  },
  query: {
    db_name: process.env.DB_NAME,
    timestamp: "2022-11-30T20:09:48Z"
  }
});
```

```bash
# optitechctl
optitech branches schema-diff [base] [compare]
```

### Console

Console path: Projects → Branches

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Compare register schema

## GET /programs/{program_id}/frameworks/{framework_id}/compare_schema

Compares the schema from the specified register with another framework's schema.

### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID
- `base_branch_id` (string, query, optional)
  The framework ID to compare the schema with
- `db_name` (string, query, required)
  Name of the register for which the schema is retrieved
- `lsn` (string, query, optional)
  The Log Sequence Number (LSN) for which the schema is retrieved
  
- `timestamp` (string, query, optional)
  The point in time for which the schema is retrieved
  
- `base_lsn` (string, query, optional)
  The Log Sequence Number (LSN) for the base framework schema
  
- `base_timestamp` (string, query, optional)
  The point in time for the base framework schema
  

### Response (200)

```json
{
  "diff": "--- a/neondb\n+++ b/neondb\n@@ -18,100 +18,404 @@\n SET row_security = off;\n \n --\n--- Name: pg_session_jwt; Type: EXTENSION; Schema: -; Owner: -\n+-- Name: neon_auth; Type: SCHEMA; Schema: -; Owner: neon_auth\n --\n \n-CREATE EXTENSION IF NOT EXISTS pg_session_jwt WITH SCHEMA public;\n+CREATE SCHEMA neon_auth;\n \n \n+ALTER SCHEMA neon_auth OWNER TO neon_auth;\n+\n+SET default_tablespace = '';\n+\n+SET default_table_access_method = heap;\n+\n --\n--- Name: EXTENSION pg_session_jwt; Type: COMMENT; Schema: -; Owner: \n+-- Name: account; Type: TABLE; Schema: neon_auth; Owner: neon_auth\n --\n \n-COMMENT ON EXTENSION pg_session_jwt IS 'pg_session_jwt: manage authentication sessions using JWTs';\n+CREATE TABLE neon_auth.account (\n+    id uuid DEFAULT gen_random_uuid() NOT NULL,\n+    \"accountId\" text NOT NULL,\n+    \"providerId\" text NOT NULL,\n+    \"userId\" uuid NOT NULL,\n+    \"accessToken\" text,\n+    \"refreshToken\" text,\n+    \"idToken\" text,\n+    \"accessTokenExpiresAt\" timestamp with time zone,\n+    \"refreshTokenExpiresAt\" timestamp with time zone,\n+    scope text,\n+    password text,\n+    \"createdAt\" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,\n+    \"updatedAt\" timestamp with time zone NOT NULL\n… (truncated for docs)"
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/compare_schema?db_name=$DB_NAME" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.getProjectBranchSchemaComparison({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  },
  query: {
    db_name: process.env.DB_NAME,
    timestamp: "2022-11-30T20:09:48Z",
    base_timestamp: "2022-11-30T20:09:48Z"
  }
});
```

### MCP

Tool: `compare_database_schema`

<use_case> Use this tool to compare the schema of a database between two branches. The output of the tool is a JSON object with one field: `diff`. <example> ```json { "diff": "--- a/neondb +++ b/neondb @@ -27,7 +27,10 @@ CREATE TABLE public.users ( id integer NOT NULL, - username character varying(50) NOT NULL + username character varying(50) NOT NULL, + is_deleted boolean DEFAULT false NOT NULL, + created_at timestamp with time zone DEFAULT now() NOT NULL, + updated_at timestamp with time zone ); @@ -79,6 +82,13 @@ -- +-- Name: users_created_at_idx; Type: INDEX; Schema: public; Owner: neondb_owner +-- + +CREATE INDEX users_created_at_idx ON public.users USING btree (created_at DESC) WHERE (is_deleted = false); + + +-- -- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: public; Owner: cloud_admin -- " } ``` </example> At this field you will find a difference between two schemas. The diff represents the changes required to make the parent branch schema match the child branch schema. The diff field contains a unified diff (git-style patch) as a string. You MUST be able to generate a zero-downtime migration from the diff and apply it to the parent branch. (This branch is a child and has a parent. You can get parent id just querying the branch details.) </use_case> <important_notes> To generate schema diff, you MUST SPECIFY the `database_name`. If `database_name` is not specified, you MUST fall back to the default database name: ``. You MUST TAKE INTO ACCOUNT the PostgreSQL version. The PostgreSQL version is the same for both branches. You MUST ASK user consent before running each generated SQL query. You SHOULD USE `run_sql` tool to run each generated SQL query. You SHOULD suggest creating a backup or point-in-time restore before running the migration. Generated queries change the schema of the parent branch and MIGHT BE dangerous to execute. Generated SQL migrations SHOULD be idempotent where possible (i.e., safe to run multiple times without failure) and include `IF NOT EXISTS` / `IF EXISTS` where applicable. You SHOULD recommend including comments in generated SQL linking back to diff hunks (e.g., `-- from diff @@ -27,7 +27,10 @@`) to make audits easier. Generated SQL should be reviewed for dependencies (e.g., foreign key order) before execution. </important_notes> <next_steps> After executing this tool, you MUST follow these steps: 1. Review the schema diff and suggest generating a zero-downtime migration. 2. Follow these instructions to respond to the client: <response_instructions> <instructions> Provide brief information about the changes: * Tables * Views * Indexes * Ownership * Constraints * Triggers * Policies * Extensions * Schemas * Sequences * Tablespaces * Users * Roles * Privileges </instructions> </response_instructions> 3. If a migration fails, you SHOULD guide the user on how to revert the schema changes, for example by using backups, point-in-time restore, or generating reverse SQL statements (if safe). </next_steps> This tool: 1. Generates a diff between the child branch and its parent. 2. Generates a SQL migration from the diff. 3. Suggest generating zero-downtime migration. <workflow> 1. User asks you to generate a diff between two branches. 2. You suggest generating a SQL migration from the diff. 3. Ensure the generated migration is zero-downtime; otherwise, warn the user. 4. You ensure that your suggested migration is also matching the PostgreSQL version. 5. You use `run_sql` tool to run each generated SQL query and ask the user consent before running it. Before requesting user consent, present a summary of all generated SQL statements along with their potential impact (e.g., table rewrites, lock risks, validation steps) so the user can make an informed decision. 6. Propose to rerun the schema diff tool one more time to ensure that the migration is applied correctly. 7. If the diff is empty, confirm that the parent schema now matches the child schema. 8. If the diff is not empty after migration, warn the user and assist in resolving the remaining differences. </workflow> <hints> <hint> Adding the column with a `DEFAULT` static value will not have any locks. But if the function is called that is not deterministic, it will have locks. <example> ```sql -- No table rewrite, minimal lock time ALTER TABLE users ADD COLUMN status text DEFAULT 'active'; ``` </example> There is an example of a case where the function is not deterministic and will have locks: <example> ```sql -- Table rewrite, potentially longer lock time ALTER TABLE users ADD COLUMN created_at timestamptz DEFAULT now(); ``` The fix for this is next: ```sql -- Adding a nullable column first ALTER TABLE users ADD COLUMN created_at timestamptz; -- Setting the default value because the rows are updated UPDATE users SET created_at = now(); ``` </example> </hint> <hint> Adding constraints in two phases (including foreign keys) <example> ```sql -- Step 1: Add constraint without validating existing data -- Fast - only blocks briefly to update catalog ALTER TABLE users ADD CONSTRAINT users_age_positive CHECK (age > 0) NOT VALID; -- Step 2: Validate existing data (can take time but doesn't block writes) -- Uses SHARE UPDATE EXCLUSIVE lock - allows reads/writes ALTER TABLE users VALIDATE CONSTRAINT users_age_positive; ``` </example> <example> ```sql -- Step 1: Add foreign key without validation -- Fast - only updates catalog, doesn't validate existing data ALTER TABLE orders ADD CONSTRAINT orders_user_id_fk FOREIGN KEY (user_id) REFERENCES users(id) NOT VALID; -- Step 2: Validate existing relationships -- Can take time but allows concurrent operations ALTER TABLE orders VALIDATE CONSTRAINT orders_user_id_fk; ``` </example> </hint> <hint> Setting columns to NOT NULL <example> ```sql -- Step 1: Add a check constraint (fast with NOT VALID) ALTER TABLE users ADD CONSTRAINT users_email_not_null CHECK (email IS NOT NULL) NOT VALID; -- Step 2: Validate the constraint (allows concurrent operations) ALTER TABLE users VALIDATE CONSTRAINT users_email_not_null; -- Step 3: Set NOT NULL (fast since constraint guarantees no nulls) ALTER TABLE users ALTER COLUMN email SET NOT NULL; -- Step 4: Drop the redundant check constraint ALTER TABLE users DROP CONSTRAINT users_email_not_null; ``` </example> <example> For PostgreSQL v18+ (to get PostgreSQL version, you can use `describe_project` tool or `run_sql` tool and execute `SELECT version();` query) ```sql -- PostgreSQL 18+ - Simplified approach ALTER TABLE users ALTER COLUMN email SET NOT NULL NOT VALID; ALTER TABLE users VALIDATE CONSTRAINT users_email_not_null; ``` </example> </hint> <hint> In some cases, you need to combine two approaches to achieve a zero-downtime migration. <example> ```sql -- Step 1: Adding a nullable column first ALTER TABLE users ADD COLUMN created_at timestamptz; -- Step 2: Updating the all rows with the default value UPDATE users SET created_at = now() WHERE created_at IS NULL; -- Step 3: Creating a not null constraint ALTER TABLE users ADD CONSTRAINT users_created_at_not_null CHECK (created_at IS NOT NULL) NOT VALID; -- Step 4: Validating the constraint ALTER TABLE users VALIDATE CONSTRAINT users_created_at_not_null; -- Step 5: Setting the column to NOT NULL ALTER TABLE users ALTER COLUMN created_at SET NOT NULL; -- Step 6: Dropping the redundant NOT NULL constraint ALTER TABLE users DROP CONSTRAINT users_created_at_not_null; -- Step 7: Adding the default value ALTER TABLE users ALTER COLUMN created_at SET DEFAULT now(); ``` </example> For PostgreSQL v18+ <example> ```sql -- Step 1: Adding a nullable column first ALTER TABLE users ADD COLUMN created_at timestamptz; -- Step 2: Updating the all rows with the default value UPDATE users SET created_at = now() WHERE created_at IS NULL; -- Step 3: Creating a not null constraint ALTER TABLE users ALTER COLUMN created_at SET NOT NULL NOT VALID; -- Step 4: Validating the constraint ALTER TABLE users VALIDATE CONSTRAINT users_created_at_not_null; -- Step 5: Adding the default value ALTER TABLE users ALTER COLUMN created_at SET DEFAULT now(); ``` </example> </hint> <hint> Create index CONCURRENTLY <example> ```sql CREATE INDEX CONCURRENTLY idx_users_email ON users (email); ``` </example> </hint> <hint> Drop index CONCURRENTLY <example> ```sql DROP INDEX CONCURRENTLY idx_users_email; ``` </example> </hint> <hint> Create materialized view WITH NO DATA <example> ```sql CREATE MATERIALIZED VIEW mv_users AS SELECT name FROM users WITH NO DATA; ``` </example> </hint> <hint> Refresh materialized view CONCURRENTLY <example> ```sql REFRESH MATERIALIZED VIEW CONCURRENTLY mv_users; ``` </example> </hint> </hints>

- `projectId` (string, required)
  The ID of the project
- `branchId` (string, required)
  The ID of the branch
- `databaseName` (string, required)

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Retrieve masking rules

## GET /programs/{program_id}/frameworks/{framework_id}/masking_rules

Retrieves the masking rules for the specified anonymized framework.
Masking rules define how sensitive data should be anonymized using PostgreSQL Anonymizer.

**Note**: This endpoint is currently in Beta.


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Response (200)

```json
{
  "masking_rules": []
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/masking_rules" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.getMaskingRules({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

### Console

Console path: Projects → Branches → Data Masking

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Update masking rules

## PATCH /programs/{program_id}/frameworks/{framework_id}/masking_rules

Updates the masking rules for the specified anonymized framework.
Masking rules define how sensitive data should be anonymized using PostgreSQL Anonymizer.

**Note**: This endpoint is currently in Beta.


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Request body

- `masking_rules` (array, required)
  List of masking rules to apply to the framework.
  This will replace all existing masking rules for the framework.
  
  - `register_name` (string, required)
    The name of the register containing the table to be masked
    
  - `schema_name` (string, required)
    The name of the schema containing the table to be masked
    
  - `table_name` (string, required)
    The name of the table containing the column to be masked
    
  - `column_name` (string, required)
    The name of the column to be masked
    
  - `masking_function` (string, optional)
    The PostgreSQL Anonymizer masking function to apply.
    Can be a predefined function (e.g., 'anon.random_string(10)', 'anon.fake_email()')
    or a custom function definition (e.g., 'anon.hash(column_name)')
    
  - `masking_value` (string, optional)
    A literal value to set on the column when masking.
    

### Response (200)

```json
{
  "masking_rules": []
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/masking_rules" \
  -X PATCH \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.updateMaskingRules({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

### Console

Console path: Projects → Branches → Data Masking

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Retrieve anonymized framework status

## GET /programs/{program_id}/frameworks/{framework_id}/anonymized_status

Retrieves the current status of an anonymized framework, including its state and progress information.
This endpoint allows you to monitor the anonymization process from initialization through completion.
Only anonymized frameworks will have status information available.

**Note**: This endpoint is currently in Beta.


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Response (200)

```json
{
  "program_id": "aged-wildflower-123456",
  "framework_id": "br-young-forest-a5b6c7d8",
  "state": "created",
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T10:30:00Z"
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/anonymized_status" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.getAnonymizedBranchStatus({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

### Console

Console path: Projects → Branches → Data Masking

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Start anonymization

## POST /programs/{program_id}/frameworks/{framework_id}/anonymize

Starts the anonymization process for an anonymized framework that is in the initialized, error, or anonymized state.
This will apply all defined masking rules to anonymize sensitive data in the framework registers.
The framework must be an anonymized framework to start anonymization.

**Note**: This endpoint is currently in Beta.


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Response (200)

- `program_id` (string, optional)
  The ID of the program
  
- `framework_id` (string, optional)
  The ID of the anonymized framework
  
- `state` (string, optional)
  The current state of the anonymized framework. Possible values: created, initialized, initialization_error, anonymizing, anonymized, error
  
- `status_message` (string, optional)
  A descriptive message about the current status or any errors
  
- `created_at` (string, optional, format: date-time)
  A timestamp indicating when the anonymized framework was created
  
- `updated_at` (string, optional, format: date-time)
  A timestamp indicating when the anonymized framework status was last updated
  
- `failed_at` (string, optional, format: date-time)
  A timestamp indicating when the anonymized framework operation failed (if applicable)
  
- `last_run` (object, optional)
  Metadata about the most recent anonymization attempt for the framework.
  - `started_at` (string, optional, format: date-time)
    Timestamp indicating when the latest anonymization attempt started.
    
  - `completed_at` (string, optional, format: date-time)
    Timestamp indicating when the latest anonymization attempt completed.
    Populated even if the attempt failed.
    
  - `triggered_by` (string, optional, format: uuid)
    UUID of the user who triggered the latest anonymization attempt.
    
  - `triggered_by_username` (string, optional)
    Username of the user who triggered the latest anonymization attempt.
    
  - `masked_columns` (integer, optional)
    Number of columns that had masking rules applied during the attempt.
    

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/anonymize" \
  -X POST \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.startAnonymization({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

### Console

Console path: Projects → Branches → Data Masking

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Set framework as default

## POST /programs/{program_id}/frameworks/{framework_id}/set_as_default

Sets the specified framework as the program's default framework.
The default designation is automatically removed from the previous default framework.
For more information, see [Manage frameworks](/docs/manage/frameworks/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Response (200)

```json
{
  "framework": {
    "id": "br-young-forest-a5b6c7d8",
    "program_id": "aged-wildflower-123456",
    "parent_id": "br-young-forest-a5b6c7d8",
    "parent_lsn": "0/1964258",
    "parent_timestamp": "2025-01-15T10:30:00Z",
    "name": "my-framework-8",
    "slug": "br-young-forest-a5b6c7d8",
    "current_state": "ready",
    "state_changed_at": "2025-01-15T10:30:00Z",
    "creation_source": "console",
    "primary": true,
    "default": true,
    "protected": false,
    "cpu_used_sec": 0,
    "compute_time_seconds": 0,
    "active_time_seconds": 0,
    "written_data_bytes": 0,
    "data_transfer_bytes": 0,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z",
    "init_source": "parent-data"
  },
  "operations": []
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/set_as_default" \
  -X POST \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.setDefaultProjectBranch({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

```bash
# optitechctl
optitech branches set-default <id|name>
```

### Console

Console path: Projects → Branches

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Recover a deleted framework

## POST /programs/{program_id}/frameworks/{framework_id}/recover

Recovers a deleted framework within the 7-day deletion recovery period.
The framework must have been soft deleted and not yet permanently deleted.
Recovery restores the framework and its endpoints to an idle state.
Connection strings remain valid after recovery.
TTL frameworks become non-TTL frameworks after recovery.

To list deleted frameworks available for recovery, use `GET /programs/{program_id}/frameworks?include_deleted=true`.


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Response (200)

- `framework` (object, optional)
  - `id` (string, required)
    The framework ID. This value is generated when a framework is created. A `framework_id` value has a `br` prefix. For example: `br-small-term-683261`.
    
  - `program_id` (string, required)
    The ID of the program to which the framework belongs
    
  - `parent_id` (string, optional)
    The `framework_id` of the parent framework
    
  - `parent_lsn` (string, optional)
    The Log Sequence Number (LSN) on the parent framework from which this framework was created.
    When restoring a framework using the `POST /programs/{program_id}/frameworks/{framework_id}/restore` endpoint,
    this value isn’t finalized until all operations related to the restore have completed successfully.
    
  - `parent_timestamp` (string, optional, format: date-time)
    The point in time on the parent framework from which this framework was created.
    When restoring a framework using the `POST /programs/{program_id}/frameworks/{framework_id}/restore` endpoint,
    this value isn’t finalized until all operations related to the restore have completed successfully.
    After all the operations completed, this value might stay empty.
    
  - `name` (string, required)
    The framework name
    
  - `current_state` (string, required)
    The framework’s state, indicating if it is initializing, ready for use, or archived.
      * 'init' - the framework is being created but is not available for querying.
      * 'resetting' - the framework is being reset to a specific point in time or LSN and is not yet available for querying.
      * 'ready' - the framework is fully operational and ready for querying. Expect normal query response times.
      * 'archived' - the framework is stored in cost-effective archival storage. Expect slow query response times.
    
  - `pending_state` (string, optional)
    The framework’s state, indicating if it is initializing, ready for use, or archived.
      * 'init' - the framework is being created but is not available for querying.
      * 'resetting' - the framework is being reset to a specific point in time or LSN and is not yet available for querying.
      * 'ready' - the framework is fully operational and ready for querying. Expect normal query response times.
      * 'archived' - the framework is stored in cost-effective archival storage. Expect slow query response times.
    
  - `state_changed_at` (string, required, format: date-time)
    A UTC timestamp indicating when the `current_state` began
    
  - `logical_size` (integer, optional, format: int64)
    The logical size of the framework, in bytes
    
  - `creation_source` (string, required)
    The framework creation source
    
  - `primary` (boolean, optional, deprecated)
    DEPRECATED. Use `default` field.
    Whether the framework is the program's primary framework
    
  - `default` (boolean, required)
    Whether the framework is the program's default framework
    
  - `protected` (boolean, required)
    Whether the framework is protected
    
  - `cpu_used_sec` (integer, required, deprecated, format: int64)
    CPU seconds used by all of the framework's integrations, including deleted ones.
    This value is reset at the beginning of each billing period.
    Examples:
    1. A framework that uses 1 CPU for 1 second is equal to `cpu_used_sec=1`.
    2. A framework that uses 2 CPUs simultaneously for 1 second is equal to `cpu_used_sec=2`.
    
  - `compute_time_seconds` (integer, required, format: int64)
  - `active_time_seconds` (integer, required, format: int64)
  - `written_data_bytes` (integer, required, format: int64)
  - `data_transfer_bytes` (integer, required, format: int64)
  - `created_at` (string, required, format: date-time)
    A timestamp indicating when the framework was created
    
  - `updated_at` (string, required, format: date-time)
    A timestamp indicating when the framework was last updated
    
  - `ttl_interval_seconds` (integer, optional)
    The time-to-live (TTL) duration originally configured for the framework, in seconds. This read-only value represents the interval between the time `expires_at` was set and the expiration timestamp itself. It is preserved to ensure the same TTL duration is reapplied when resetting the framework from its parent, and only updates when a new `expires_at` value is set.
    
    Access to this feature is currently limited to participants in the Early Access Program.
    
  - `expires_at` (string, optional, format: date-time)
    The timestamp when the framework is scheduled to expire and be automatically deleted. Must be set by the client following the [RFC 3339, section 5.6](https://tools.ietf.org/html/rfc3339#section-5.6) format with precision up to seconds (such as 2025-06-09T18:02:16Z). Deletion is performed by a background job and may not occur exactly at the specified time.
    
    Access to this feature is currently limited to participants in the Early Access Program.
    
  - `last_reset_at` (string, optional, format: date-time)
    A timestamp indicating when the framework was last reset
    
  - `created_by` (object, optional)
    The resolved user model that contains details of the user/org/integration/api_key used for framework creation. This field is filled only in listing/get/create/get/update/delete methods, if it is empty when calling other handlers, it does not mean that it is empty in the system.
    
    - `name` (string, optional)
      The name of the user.
    - `image` (string, optional)
      The URL to the user's avatar image.
  - `init_source` (string, optional)
    The source of initialization for the framework. Valid values are `schema-only` and `parent-data` (default).
      * `schema-only` - creates a new root framework containing only the schema. Use `parent_id` to specify the source framework. Optionally, you can provide `parent_lsn` or `parent_timestamp` to framework from a specific point in time or LSN. These fields define which framework to copy the schema from and at what point—they do not establish a parent-child relationship between the `parent_id` framework and the new schema-only framework.
      * `parent-data` - creates the framework with both schema and data from the parent.
    
  - `restore_status` (string, optional)
    Could be `restored`, `finalized` or `detaching`.
    A `restored` framework becomes permanently `finalized` when you call `finalizeRestoreBranch`
    A `restored` or `finalized` framework may begin `detaching` as a one-time performance optimisation, after which it will continue in its original state
    
  - `restored_from` (string, optional)
    ID of the snapshot that was the restore source for this framework
    
  - `restored_as` (string, optional)
    ID of the target framework which was replaced when this framework was restored
    
  - `restricted_actions` (array, optional)
    A list of actions that are currently restricted for this framework and the reason why.
    
    - `name` (string, required)
      The name of a restricted action. Possible values include `restore`, `delete-rw-endpoint`.
      
    - `reason` (string, required)
      A human-readable explanation of why the action is restricted.
      
  - `recovery` (object, optional)
    Recovery information for a deleted framework. Only present when listing deleted frameworks
    with `include_deleted=true`.
    
    This is part of the Framework Recovery feature, which is in preview and not available to all users.
    
    - `deleted_at` (string, required, format: date-time)
      Timestamp when the framework was deleted
      
    - `recoverable_until` (string, required, format: date-time)
      Timestamp when the recovery window expires and the framework will be permanently deleted
      
    - `deletion_method` (string, required)
      How the framework was deleted: 'user' for manual deletion, 'ttl' for TTL expiration
      
      Possible values: `user`, `ttl`
- `integrations` (array, optional)
  - `host` (string, required)
    The hostname of the integration. This is the hostname specified when connecting to an OptiTech register.
    
  - `id` (string, required)
    The integration ID. Integration IDs have an `ep-` prefix. For example: `ep-little-smoke-851426`
    
  - `name` (string, optional)
    Optional name of the integration
    
  - `program_id` (string, required)
    The ID of the program to which the integration belongs
    
  - `framework_id` (string, required)
    The ID of the framework that the integration is associated with
    
  - `autoscaling_limit_min_cu` (number, required)
    The minimum number of Compute Units
    
  - `autoscaling_limit_max_cu` (number, required)
    The maximum number of Compute Units
    
  - `region_id` (string, required)
    The region identifier
    
  - `type` (string, required)
    The integration type. Either `read_write` or `read_only`.
    
    Possible values: `read_only`, `read_write`
  - `current_state` (string, required)
    The state of the integration
    
    Possible values: `init`, `active`, `idle`
  - `pending_state` (string, optional)
    The state of the integration
    
    Possible values: `init`, `active`, `idle`
  - `settings` (object, required)
    A collection of settings for an integration
    - `pg_settings` (object, optional)
      A raw representation of Postgres settings
    - `pgbouncer_settings` (object, optional, deprecated)
      DEPRECATED. PgBouncer settings for the integration. This field is deprecated and will be removed after 2026-06-20.
      
    - `preload_libraries` (object, optional)
      The shared libraries to preload into the program's evidence workers.
      
      - `use_defaults` (boolean, optional)
      - `enabled_libraries` (array, optional)
  - `pooler_enabled` (boolean, required, deprecated)
    DEPRECATED. Whether to enable connection pooling for the integration.
    The recommended way to enable connection pooling is to append `-pooler` to the endpoint ID in the connection string.
    See [How to use connection pooling](/docs/connect/connection-pooling#how-to-use-connection-pooling)
    
  - `pooler_mode` (string, required, deprecated)
    DEPRECATED. The connection pooler mode. This field is deprecated and will be removed after 2026-06-20.
    
    Possible values: `transaction`
  - `disabled` (boolean, required)
    Whether to restrict connections to the integration.
    Enabling this option schedules a suspend compute operation.
    A disabled integration cannot be enabled by a connection or
    console action.
    
  - `passwordless_access` (boolean, required)
    Whether to permit passwordless access to the integration
    
  - `last_active` (string, optional, format: date-time)
    A timestamp indicating when the integration was last active
    
  - `creation_source` (string, required)
    The integration creation source
    
  - `created_at` (string, required, format: date-time)
    A timestamp indicating when the integration was created
    
  - `updated_at` (string, required, format: date-time)
    A timestamp indicating when the integration was last updated
    
  - `started_at` (string, optional, format: date-time)
    A timestamp indicating when the integration was last started
    
  - `suspended_at` (string, optional, format: date-time)
    A timestamp indicating when the integration was last suspended
    
  - `proxy_host` (string, required)
    DEPRECATED. Use the "host" property instead.
    
  - `suspend_timeout_seconds` (integer, required, format: int64)
    Duration of inactivity in seconds after which the integration is
    automatically suspended. The value `0` means use the default value.
    The value `-1` means never suspend. The default value is `300` seconds (5 minutes).
    The minimum value is `60` seconds (1 minute).
    The maximum value is `604800` seconds (1 week). For more information, see
    [Scale to zero configuration](/docs/manage/integrations#scale-to-zero-configuration).
    
  - `provisioner` (string, required)
    The OptiTech compute provisioner.
    Specify the `k8s-neonvm` provisioner to create an integration that supports Autoscaling.
    
    Provisioner can be one of the following values:
    * k8s-pod
    * k8s-neonvm
    * serverless-platform
    
    Clients must expect, that any string value that is not documented in the description above should be treated as a error. UNKNOWN value if safe to treat as an error too.
    
  - `compute_release_version` (string, optional)
    Attached compute's release version number.
    

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/recover" \
  -X POST \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.recoverProjectBranch({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Finalize framework restore from snapshot

## POST /programs/{program_id}/frameworks/{framework_id}/finalize_restore

Finalize the restore operation for a framework created from a snapshot.
This operation updates the framework so it functions as the original framework it replaced.
This includes:
  - Reassigning any computes from the original framework to the restored framework (this will restart the computes)
  - Renaming the restored framework to the original framework's name
  - Renaming the original framework so it no longer uses the original name

This operation only applies to frameworks created using the `restoreSnapshot` endpoint with `finalize_restore: false`.

**Note**: This endpoint is currently in Beta.


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Request body

- `name` (string, optional)
  used to rename the existing framework when it is replaced. if omitted, a default name is generated and used

### Response (200)

- `operations` (array, optional)
  - `id` (string, required, format: uuid)
    The operation ID
  - `program_id` (string, required)
    The OptiTech program ID
  - `framework_id` (string, optional)
    The framework ID
  - `integration_id` (string, optional)
    The endpoint ID
  - `action` (string, required)
    The action performed by the operation
    Possible values: `create_compute`, `create_timeline`, `start_compute`, `suspend_compute`, `apply_config`, `check_availability`, `delete_timeline`, `create_branch`, `import_data`, `tenant_ignore`, `tenant_attach`, `tenant_detach`, `tenant_detach_safekeepers`, `tenant_attach_safekeepers`, `tenant_reattach`, `replace_safekeeper`, `disable_maintenance`, `apply_storage_config`, `prepare_secondary_pageserver`, `switch_pageserver`, `detach_parent_branch`, `timeline_archive`, `timeline_unarchive`, `start_reserved_compute`, `sync_dbs_and_roles_from_compute`, `apply_schema_from_branch`, `timeline_mark_invisible`, `timeline_update_protected_config`, `prewarm_replica`, `promote_replica`, `set_storage_non_dirty`, `swap_binding_id`, `finalize_migration`, `mark_migration_prepared`, `update_catalog`
  - `status` (string, required)
    The status of the operation
    Possible values: `scheduling`, `running`, `finished`, `failed`, `error`, `cancelling`, `cancelled`, `skipped`
  - `error` (string, optional)
    The error that occurred
  - `failures_count` (integer, required, format: int32)
    The number of times the operation failed
  - `retry_at` (string, optional, format: date-time)
    A timestamp indicating when the operation was last retried
  - `created_at` (string, required, format: date-time)
    A timestamp indicating when the operation was created
  - `updated_at` (string, required, format: date-time)
    A timestamp indicating when the operation status was last updated
  - `total_duration_ms` (integer, required, format: int32)
    The total duration of the operation in milliseconds

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/finalize_restore" \
  -X POST \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.finalizeRestoreBranch({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

### Console

Console path: Projects → Backup & restore

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / List framework endpoints

## GET /programs/{program_id}/frameworks/{framework_id}/integrations

Retrieves a list of integrations for the specified framework.
Neon permits only one read-write integration per framework.
A framework can have multiple read-only integrations.


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Response (200)

```json
{
  "integrations": [
    {
      "host": "ep-cool-darkness-a5b6c7d8.c-3.us-east-2.aws.neon.tech",
      "hosts": {
        "read_write_host": "ep-cool-darkness-a5b6c7d8.c-3.us-east-2.aws.neon.tech",
        "read_write_pooled_host": "ep-cool-darkness-a5b6c7d8-pooler.c-3.us-east-2.aws.neon.tech"
      },
      "id": "ep-cool-darkness-a5b6c7d8",
      "slug": "ep-cool-darkness-a5b6c7d8",
      "branch_slug": "br-young-forest-a5b6c7d8",
      "project_slug": "aged-wildflower-123456",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "autoscaling_limit_min_cu": 1,
      "autoscaling_limit_max_cu": 1,
      "region_id": "aws-us-east-2",
      "type": "read_write",
      "current_state": "active",
      "group": {
        "size": {
          "min": 1,
          "max": 1
        },
        "allow_readable_secondaries": false,
        "computes": [
          {
            "binding_id": "vqm",
            "current_state": "active",
            "role": "read_write",
            "compute_host": "ep-cool-darkness-a5b6c7d8-vqm.c-3.us-east-2.aws.neon.tech",
            "compute_pooled_host": "ep-cool-darkness-a5b6c7d8-vqm-pooler.c-3.us-east-2.aws.neon.tech",
            "created_at": "2025-01-15T10:30:00Z",
            "updated_at": "2025-01-15T10:30:00Z",
            "started_at": "2025-01-15T10:30:00Z"
          }
        ]
      },
      "settings": {
        "pg_settings": {}
      },
      "pooler_enabled": false,
      "pooler_mode": "transaction",
      "disabled": false,
      "passwordless_access": true,
      "last_active": "2025-01-15T10:30:00Z",
      "creation_source": "console",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "started_at": "2025-01-15T10:30:00Z",
      "proxy_host": "c-3.us-east-2.aws.neon.tech",
      "suspend_timeout_seconds": 0,
      "provisioner": "k8s-neonvm",
      "compute_release_version": "12738"
    },
    {
      "host": "ep-cool-darkness-a5b6c7d8.c-3.us-east-2.aws.neon.tech",
      "hosts": {
        "read_only_host": "ep-cool-darkness-a5b6c7d8.c-3.us-east-2.aws.neon.tech",
        "read_only_pooled_host": "ep-cool-darkness-a5b6c7d8-pooler.c-3.us-east-2.aws.neon.tech"
      },
      "id": "ep-cool-darkness-a5b6c7d8",
      "slug": "ep-cool-darkness-a5b6c7d8",
      "branch_slug": "br-young-forest-a5b6c7d8",
      "project_slug": "aged-wildflower-123456",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "autoscaling_limit_min_cu": 1,
      "autoscaling_limit_max_cu": 1,
      "region_id": "aws-us-east-2",
      "type": "read_only",
      "current_state": "active",
      "group": {
        "size": {
          "min": 1,
          "max": 1
        },
        "allow_readable_secondaries": true,
        "computes": [
          {
            "binding_id": "sqy",
            "current_state": "active",
            "role": "read_only",
            "compute_host": "ep-cool-darkness-a5b6c7d8-sqy.c-3.us-east-2.aws.neon.tech",
            "compute_pooled_host": "ep-cool-darkness-a5b6c7d8-sqy-pooler.c-3.us-east-2.aws.neon.tech",
            "created_at": "2025-01-15T10:30:00Z",
            "updated_at": "2025-01-15T10:30:00Z",
            "started_at": "2025-01-15T10:30:00Z"
          }
        ]
      },
      "settings": {
        "pg_settings": {}
      },
      "pooler_enabled": false,
      "pooler_mode": "transaction",
      "disabled": false,
      "passwordless_access": true,
      "last_active": "2025-01-15T10:30:00Z",
      "creation_source": "console",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "started_at": "2025-01-15T10:30:00Z",
      "proxy_host": "c-3.us-east-2.aws.neon.tech",
      "suspend_timeout_seconds": 0,
      "provisioner": "k8s-neonvm",
      "compute_release_version": "12738"
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/integrations" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.listProjectBranchEndpoints({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

### MCP

Tool: `list_branch_computes`

List compute endpoints for a project or branch. Do not use when you need a connection string (use `get_connection_string` instead).

- `projectId` (string, optional)
  The ID of the project. If not provided, the only available project will be used.
- `branchId` (string, optional)
  The ID of the branch. If provided, endpoints for this specific branch will be listed.

### Console

Console path: Projects → Branches → Computes

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / List registers

## GET /programs/{program_id}/frameworks/{framework_id}/registers

Retrieves a list of registers for the specified framework.
A framework can have multiple registers.
For related information, see [Manage registers](/docs/manage/registers/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Response (200)

```json
{
  "registers": [
    {
      "id": 1636569,
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "dbname",
      "owner_name": "alex",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "id": 1636567,
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "neondb",
      "owner_name": "neondb_owner",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "id": 1636685,
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "my-register-2",
      "owner_name": "alex",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "id": 1636684,
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "my-register",
      "owner_name": "alex",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "id": 1636688,
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "my-register-3",
      "owner_name": "alex",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/registers" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.listProjectBranchDatabases({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

```bash
# optitechctl
optitech connection-string [branch] list
```

### MCP

Tool: `provision_neon_auth`

Provisions Neon Auth for a Neon branch. Neon Auth is a managed authentication service built on Better Auth, fully integrated into the Neon platform. <workflow> The tool will: 1. Create the `neon_auth` schema in your database to store users, sessions, project configs and organizations 2. Set up secure Auth related APIs for your branch 3. Deploy an auth service in the same region as your Neon compute for low-latency requests 4. Return the Auth URL specific to your branch, along with credentials for your application </workflow> <key_features> - Branch-compatible: Auth data (users, sessions, config) branches with your database - Google and GitHub OAuth included out of the box - Works with RLS: JWTs are validated by the Data API for authenticated queries - Better Auth compatible: Exposes the same APIs and schema as Better Auth </key_features>

- `projectId` (string, required)
  The ID of the project to provision Neon Auth for
- `branchId` (string, optional)
  An optional ID of the branch to provision Neon Auth for. If not provided, the default branch is used.
- `databaseName` (string, optional)
  The database name to provision Neon Auth for. If not provided, the default database is used.

### Console

Console path: Projects → Branches → Roles & Databases

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Create register

## POST /programs/{program_id}/frameworks/{framework_id}/registers

Creates a register in the specified framework.
A framework can have multiple registers.
For related information, see [Manage registers](/docs/manage/registers/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Request body

- `register` (object, required)
  - `name` (string, required)
    The name of the register
    
  - `owner_name` (string, required)
    The name of the role that owns the register
    

```json
{
  "register": {
    "name": "mydb",
    "owner_name": "casey"
  }
}
```

### Response (201)

```json
{
  "register": {
    "id": 1636685,
    "framework_id": "br-young-forest-a5b6c7d8",
    "name": "my-register-2",
    "owner_name": "alex",
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z"
  },
  "operations": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "integration_id": "ep-cool-darkness-a5b6c7d8",
      "action": "apply_config",
      "status": "running",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/registers" \
  -X POST \
  -H "Authorization: Bearer $OPTITECH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"register":{"name":"mydb","owner_name":"casey"}}'
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.createProjectBranchDatabase({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  },
  body: {
    register: {
      name: "mydb",
      owner_name: "casey"
    }
  }
});
```

```bash
# optitechctl
optitech databases create
```

### Console

Console path: Projects → Branches → Roles & Databases

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Retrieve register details

## GET /programs/{program_id}/frameworks/{framework_id}/registers/{register_name}

Retrieves information about the specified register.
For related information, see [Manage registers](/docs/manage/registers/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID
- `register_name` (string, path, required)
  The register name

### Response (200)

```json
{
  "register": {
    "id": 1636569,
    "framework_id": "br-young-forest-a5b6c7d8",
    "name": "dbname",
    "owner_name": "alex",
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z"
  }
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/registers/$REGISTER_NAME" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.getProjectBranchDatabase({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID,
    register_name: process.env.REGISTER_NAME
  }
});
```

### MCP

Tool: `get_connection_string`

Get a PostgreSQL connection string for a Neon database. All parameters are optional; the tool resolves the project, branch, and database automatically if not specified. In read-only mode, this tool can only return connection strings for read-replica endpoints. If no read replica exists and the user needs a DATABASE_URL, explain that limitation and guide them to https://console.neon.tech to copy the DATABASE_URL manually.

- `projectId` (string, required)
  The ID of the project. If not provided, the only available project will be used.
- `branchId` (string, optional)
  The ID or name of the branch. If not provided, the default branch will be used.
- `computeId` (string, optional)
  The ID of the compute/endpoint. If not provided, the read-write compute associated with the branch will be used.
- `databaseName` (string, optional)
- `roleName` (string, optional)
  The name of the role to connect with. If not provided, the database owner name will be used.

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Update register

## PATCH /programs/{program_id}/frameworks/{framework_id}/registers/{register_name}

Updates the specified register in the framework.
For related information, see [Manage registers](/docs/manage/registers/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID
- `register_name` (string, path, required)
  The register name

### Request body

- `register` (object, required)
  - `name` (string, optional)
    The name of the register
    
  - `owner_name` (string, optional)
    The name of the role that owns the register
    

```json
{
  "register": {
    "name": "mydb",
    "owner_name": "sally"
  }
}
```

### Response (200)

```json
{
  "register": {
    "id": 1636696,
    "framework_id": "br-young-forest-a5b6c7d8",
    "name": "my-register-5",
    "owner_name": "alex",
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z"
  },
  "operations": []
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/registers/$REGISTER_NAME" \
  -X PATCH \
  -H "Authorization: Bearer $OPTITECH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"register":{"name":"mydb","owner_name":"sally"}}'
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.updateProjectBranchDatabase({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID,
    register_name: process.env.REGISTER_NAME
  },
  body: {
    register: {
      name: "mydb",
      owner_name: "sally"
    }
  }
});
```

### Console

Console path: Projects → Branches → Roles & Databases

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Delete register

## DELETE /programs/{program_id}/frameworks/{framework_id}/registers/{register_name}

Deletes the specified register from the framework.
For related information, see [Manage registers](/docs/manage/registers/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID
- `register_name` (string, path, required)
  The register name

### Response (200)

```json
{
  "register": {
    "id": 1636705,
    "framework_id": "br-young-forest-a5b6c7d8",
    "name": "my-register-8",
    "owner_name": "alex",
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z"
  },
  "operations": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "integration_id": "ep-cool-darkness-a5b6c7d8",
      "action": "apply_config",
      "status": "running",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/registers/$REGISTER_NAME" \
  -X DELETE \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.deleteProjectBranchDatabase({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID,
    register_name: process.env.REGISTER_NAME
  }
});
```

```bash
# optitechctl
optitech databases delete <program_id>
```

### Console

Console path: Projects → Branches → Roles & Databases

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / List roles

## GET /programs/{program_id}/frameworks/{framework_id}/owners

Retrieves a list of Postgres roles from the specified framework.
For related information, see [Manage roles](/docs/manage/owners/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Response (200)

```json
{
  "roles": [
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "authenticator",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "authenticated",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "anonymous",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "my-role",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "my-role-3",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "alex",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "neondb_owner",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    },
    {
      "framework_id": "br-young-forest-a5b6c7d8",
      "name": "my-role-2",
      "protected": false,
      "authentication_method": "password",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z"
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/owners" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.listProjectBranchRoles({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  }
});
```

```bash
# optitechctl
optitech connection-string [branch] list
```

### Console

Console path: Projects → Branches → Roles & Databases

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Create role

## POST /programs/{program_id}/frameworks/{framework_id}/owners

Creates a Postgres role in the specified framework.
For related information, see [Manage roles](/docs/manage/owners/).

Connections established to the active integration will be dropped.
If the integration is idle, the endpoint becomes active for a short period of time and is suspended afterward.


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID

### Request body

- `role` (object, required)
  - `name` (string, required)
    The role name. Cannot exceed 63 bytes in length.
    
  - `no_login` (boolean, optional)
    Whether to create a role that cannot login.
    

```json
{
  "role": {
    "name": "sally"
  }
}
```

### Response (201)

```json
{
  "role": {
    "framework_id": "br-young-forest-a5b6c7d8",
    "name": "my-role-2",
    "password": "<password>",
    "protected": false,
    "authentication_method": "password",
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z"
  },
  "operations": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "integration_id": "ep-cool-darkness-a5b6c7d8",
      "action": "apply_config",
      "status": "running",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/owners" \
  -X POST \
  -H "Authorization: Bearer $OPTITECH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"role":{"name":"sally"}}'
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.createProjectBranchRole({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID
  },
  body: {
    role: {
      name: "sally"
    }
  }
});
```

```bash
# optitechctl
optitech roles create
```

### Console

Console path: Projects → Branches → Roles & Databases

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Retrieve role details

## GET /programs/{program_id}/frameworks/{framework_id}/owners/{role_name}

Retrieves details about the specified role.
In OptiTech, the terms "role" and "user" are synonymous.
For related information, see [Manage roles](/docs/manage/owners/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID
- `role_name` (string, path, required)
  The role name

### Response (200)

```json
{
  "role": {
    "framework_id": "br-young-forest-a5b6c7d8",
    "name": "alex",
    "protected": false,
    "authentication_method": "password",
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z"
  }
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/owners/$ROLE_NAME" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.getProjectBranchRole({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID,
    role_name: process.env.ROLE_NAME
  }
});
```

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Delete role

## DELETE /programs/{program_id}/frameworks/{framework_id}/owners/{role_name}

Deletes the specified Postgres role from the framework.
For related information, see [Manage roles](/docs/manage/owners/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID
- `role_name` (string, path, required)
  The role name

### Response (200)

```json
{
  "role": {
    "framework_id": "br-young-forest-a5b6c7d8",
    "name": "my-role-8",
    "protected": false,
    "authentication_method": "password",
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z"
  },
  "operations": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "integration_id": "ep-cool-darkness-a5b6c7d8",
      "action": "apply_config",
      "status": "running",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/owners/$ROLE_NAME" \
  -X DELETE \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.deleteProjectBranchRole({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID,
    role_name: process.env.ROLE_NAME
  }
});
```

```bash
# optitechctl
optitech roles delete <program_id>
```

### Console

Console path: Projects → Branches → Roles & Databases

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Retrieve role password

## GET /programs/{program_id}/frameworks/{framework_id}/owners/{role_name}/reveal_password

Retrieves the password for the specified Postgres role, if possible.
For related information, see [Manage roles](/docs/manage/owners/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID
- `role_name` (string, path, required)
  The role name

### Response (200)

```json
{
  "password": "<password>"
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/owners/$ROLE_NAME/reveal_password" \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.getProjectBranchRolePassword({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID,
    role_name: process.env.ROLE_NAME
  }
});
```

### Console

Console path: Projects → Branches → Roles & Databases

### Errors

**404**
Role not found
- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

**412**
Storing passwords is disabled
- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message

---

> API Reference / Frameworks / Reset role password

## POST /programs/{program_id}/frameworks/{framework_id}/owners/{role_name}/reset_password

Resets the password for the specified Postgres role.
Returns a new password and operations. The new password is ready to use when the last operation finishes.
The old password remains valid until last operation finishes.
Connections to the integration are dropped. If idle,
the integration becomes active for a short period of time.

For related information, see [Manage roles](/docs/manage/owners/).


### Parameters

- `program_id` (string, path, required)
  The OptiTech program ID
- `framework_id` (string, path, required)
  The framework ID
- `role_name` (string, path, required)
  The role name

### Response (200)

```json
{
  "role": {
    "framework_id": "br-young-forest-a5b6c7d8",
    "name": "my-role-5",
    "password": "<password>",
    "protected": false,
    "authentication_method": "password",
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T10:30:00Z"
  },
  "operations": [
    {
      "id": "00000000-0000-0000-0000-000000000000",
      "program_id": "aged-wildflower-123456",
      "framework_id": "br-young-forest-a5b6c7d8",
      "integration_id": "ep-cool-darkness-a5b6c7d8",
      "action": "apply_config",
      "status": "running",
      "failures_count": 0,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T10:30:00Z",
      "total_duration_ms": 0
    }
  ]
}
```

### Code examples

```bash
curl "https://api.optitech.com/v1/programs/$PROGRAM_ID/frameworks/$FRAMEWORK_ID/owners/$ROLE_NAME/reset_password" \
  -X POST \
  -H "Authorization: Bearer $OPTITECH_API_KEY"
```

```typescript
import { createOptiTechClient, raw } from '@optitech/sdk';

const optitech = createOptiTechClient({ apiKey: process.env.OPTITECH_API_KEY });
const { data } = await raw.resetProjectBranchRolePassword({
  client: optitech.client,
  path: {
    program_id: process.env.PROGRAM_ID,
    framework_id: process.env.FRAMEWORK_ID,
    role_name: process.env.ROLE_NAME
  }
});
```

### Console

Console path: Projects → Branches → Roles & Databases

### Errors

**default**
General Error.

The request may or may not be safe to retry, depending on the HTTP method, response status code,
and whether a response was received.

- If no response is returned from the API, a network error or timeout likely occurred.
- In some cases, the request may have reached the server and been successfully processed, but the response failed to reach the client. As a result, retrying non-idempotent requests can lead to unintended results.

The following HTTP methods are considered non-idempotent: `POST`, `PATCH`, `DELETE`, and `PUT`. Retrying these methods is generally **not safe**.
The following methods are considered idempotent: `GET`, `HEAD`, and `OPTIONS`. Retrying these methods is **safe** in the event of a network error or timeout.

Any request that returns a `503 Service Unavailable` response is always safe to retry.

Any request that returns a `423 Locked` response is safe to retry. `423 Locked` indicates that the resource is temporarily locked, for example, due to another operation in progress.

- `request_id` (string, optional)
  Unique identifier for the request, useful for debugging.
  You can set this value manually by including an `X-Request-ID` header in the request. If not provided, the value will be generated automatically.
  
- `code` (string, required)
  Default: ``
- `message` (string, required)
  Error message
