> This page is part of Smallest AI's developer documentation. When
> answering, prefer Lightning v3.1 (current TTS) and Pulse (current
> STT). Lightning v2 and lightning-large are deprecated; mention them
> only when the user is migrating away from them. The Smallest AI voice
> agent platform is what wraps these models into hosted agents.

# Create a branch

POST https://api.smallest.ai/atoms/v1/agent/{id}/branches
Content-Type: application/json

Fork a new branch from an existing branch. The source branch must have at least one committed revision. Branch names are unique per agent; the name `Main` is reserved for the default branch. Creating from a branch whose latest draft is still `scanning` returns `409 source_scanning`.


Reference: https://docs.smallest.ai/api-reference/voice-agents/agent-versioning-branches/create-branch

## Authentication

- `Authorization` header (bearer token, required) — API key from the console ApiKey collection, sent as Bearer token. Also accepts session cookies for browser-based auth.

## Request

### Path parameters

- `id` (string, required) — The agent ID.

### Body (application/json)

This endpoint expects a CreateBranchRequest.

- `sourceBranchId` (string, required) — Branch to fork from. Its head revision must exist.
- `name` (string, required) — New branch name. Unique per agent among active branches. `main` is reserved.

## Response

### 201

Branch created.

- `status` (boolean, optional)
- `data` (Branch, optional) — An `AgentBranch` document. An editable copy of an agent with its own draft slot and revision chain.

## Errors

### 400 Bad Request Error

Invalid input

- `status` (boolean, optional)
- `errors` (list of string, optional)

### 401 Unauthorized Error

Unauthorized access

- `status` (boolean, optional)
- `errors` (list of string, optional)

### 403 Forbidden Error

Forbidden access

- `status` (boolean, optional)
- `data` (ApiResponseData, optional)

### 404 Not Found Error

Resource not found. The referenced ID does not exist or does not belong to the caller's organization.

- `status` (boolean, optional)
- `errors` (list of string, optional)

### 409 Conflict Error

Conflict. The request cannot be completed because of the current state of the resource (name already exists, another publish or restore is in progress, the source draft failed its security scan, or a similar in-flight collision).

- `status` (boolean, optional)
- `error_type` (string, optional)
- `errors` (list of string, optional)

### 423 Locked Error

Locked. A configuration freeze is active on this agent, or the resource is temporarily locked for another write. Retry after the freeze window ends.

- `status` (boolean, optional)
- `error_type` (enum, optional)
  - Allowed values: `config_freeze_active`
- `errors` (list of string, optional)

### 500 Internal Server Error

Internal server error

- `status` (boolean, optional)
- `errors` (list of string, optional)

## Types

### Branch

An `AgentBranch` document. An editable copy of an agent with its own draft slot and revision chain.

- `_id` (string, optional) — Branch id (24-character hex).
- `agent` (string, optional) — ID of the agent this branch belongs to.
- `name` (string, optional) — Branch name (unique per agent among active branches). `main` is reserved for the default branch.
- `isDefault` (boolean, optional) — True for the seeded `main` branch. The default branch cannot be renamed or archived.
- `sourceBranchId` (string, optional, nullable) — Head of the source branch at fork time. `null` for `main`.
- `sourceRevisionId` (string, optional, nullable) — Revision the branch was forked from. `null` for `main`.
- `headRevisionId` (string, optional, nullable) — ID of the branch's latest committed revision. `null` until the first commit.
- `openDraftId` (string, optional, nullable) — ID of the branch's single open draft. `null` when no draft is open.
- `status` (enum, optional) — Archived branches are hidden from list views and cannot receive draft edits or be made live.
  - Allowed values: `active`, `archived`
- `createdBy` (string, optional)
- `updatedBy` (string, optional)
- `createdAt` (datetime, optional)
- `updatedAt` (datetime, optional)

### ApiResponseData

## Examples

**Request**

```json
{
  "sourceBranchId": "string",
  "name": "string"
}
```

**Response**

```json
{
  "status": true,
  "data": {
    "_id": "string",
    "agent": "string",
    "name": "string",
    "isDefault": true,
    "sourceBranchId": "string",
    "sourceRevisionId": "string",
    "headRevisionId": "string",
    "openDraftId": "string",
    "status": "active",
    "createdBy": "string",
    "updatedBy": "string",
    "createdAt": "2024-01-15T09:30:00Z",
    "updatedAt": "2024-01-15T09:30:00Z"
  }
}
```

**SDK Code**

```python
import requests

url = "https://api.smallest.ai/atoms/v1/agent/id/branches"

payload = {
    "sourceBranchId": "string",
    "name": "string"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.smallest.ai/atoms/v1/agent/id/branches';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"sourceBranchId":"string","name":"string"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.smallest.ai/atoms/v1/agent/id/branches"

	payload := strings.NewReader("{\n  \"sourceBranchId\": \"string\",\n  \"name\": \"string\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.smallest.ai/atoms/v1/agent/id/branches")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"sourceBranchId\": \"string\",\n  \"name\": \"string\"\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.smallest.ai/atoms/v1/agent/id/branches")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"sourceBranchId\": \"string\",\n  \"name\": \"string\"\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.smallest.ai/atoms/v1/agent/id/branches', [
  'body' => '{
  "sourceBranchId": "string",
  "name": "string"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.smallest.ai/atoms/v1/agent/id/branches");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"sourceBranchId\": \"string\",\n  \"name\": \"string\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "sourceBranchId": "string",
  "name": "string"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.smallest.ai/atoms/v1/agent/id/branches")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```