---
title: "Create thread (idempotent requestId)"
description: "Creates an approval pointer; execution still requires human approval. Org API-key runtime calls return 501 until tenant runtime routing is configured."
---

> Documentation Index
> Fetch the complete documentation index at: https://tryshiba.dev/llms.txt
> Use this file to discover all available pages before exploring further.

Path: Shiba public API

`POST /threads`

Creates an approval pointer; execution still requires human approval. Org API-key runtime calls return 501 until tenant runtime routing is configured.

## Authentication

- `bearerAuth`, http, header `Authorization`, format `API key`

## Request body

- `requestId` (`post/threads.requestId`; string, required)
  - maxLength 191
- `projectId` (`post/threads.projectId`; string, optional) — Repository URL in self-hosted shiba.
- `repoUrl` (`post/threads.repoUrl`; string, optional)
- `message` (`post/threads.message`; string, optional)
- `task` (`post/threads.task`; string, optional)
- `publishPullRequest` (`post/threads.publishPullRequest`; boolean, optional)
- `customAgentId` (`post/threads.customAgentId`; string, optional) — Select an available org-scoped bot profile; effective instructions, route, version and expected outputs freeze into the human approval.
- `expectedDeliverables` (`post/threads.expectedDeliverables`; array<string>, optional) — Optional approval-frozen workspace output paths, in delivery order. Paths are unique ignoring case; relative, non-hidden ASCII segments only (letters/digits, dot, underscore, hyphen, internal spaces), no empty/dot/parent/absolute segments or leading/trailing spaces. Only md/txt/json/csv. Requested complete UTF-8 nonempty files are capped at 16384 bytes each and 65536 bytes total; JSON must parse. Collection checks do not assess semantic quality.
  - minLength 1; maxLength 240; pattern `^(?!.* (?:/|$))(?:[A-Za-z0-9][A-Za-z0-9._ -]*/)*[A-Za-z0-9][A-Za-z0-9._ -]*\.(?:[mM][dD]|[tT][xX][tT]|[jJ][sS][oO][nN]|[cC][sS][vV])$`

## Example request

```json
{
  "requestId": "string",
  "projectId": "string",
  "repoUrl": "string",
  "message": "string",
  "task": "string",
  "publishPullRequest": true,
  "customAgentId": "string",
  "expectedDeliverables": [
    "string"
  ]
}
```

## Code samples

### cURL

```bash
curl --request POST \
  --url '<base-url>/api/v1/threads' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "requestId": "string",
  "projectId": "string",
  "repoUrl": "string",
  "message": "string",
  "task": "string",
  "publishPullRequest": true,
  "customAgentId": "string",
  "expectedDeliverables": [
    "string"
  ]
}
'
```

### TypeScript

```typescript
const url = '<base-url>/api/v1/threads';
const options = {
  method: 'POST',
  headers: {'Content-Type': 'application/json', Authorization: 'Bearer <token>'},
  body: JSON.stringify({
    requestId: 'string',
    projectId: 'string',
    repoUrl: 'string',
    message: 'string',
    task: 'string',
    publishPullRequest: true,
    customAgentId: 'string',
    expectedDeliverables: ['string']
  })
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));
```

### Python

```python
import requests

url = "<base-url>/api/v1/threads"

payload = {
    "requestId": "string",
    "projectId": "string",
    "repoUrl": "string",
    "message": "string",
    "task": "string",
    "publishPullRequest": True,
    "customAgentId": "string",
    "expectedDeliverables": ["string"]
}
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer <token>"
}

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

print(response.text)
```

## Responses

### 200

Thread or approval receipt

### 501

Tenant runtime unavailable for org API keys


Source: https://tryshiba.dev/reference/api/post/threads/index.md
