Bits
Bits are the executable units of work within a chain. They support multiple views: tree, matrix, calendar, and gantt.
Endpoints
| Method | Path | Description | Auth | Rate Limit |
|---|---|---|---|---|
| GET | /bits | List bits (supports ?chainId and filters) | JWT | 60/min |
| GET | /bits/tree | Hierarchy tree view | JWT | 30/min |
| GET | /bits/matrix | Matrix view | JWT | 30/min |
| GET | /bits/calendar | Calendar view | JWT | 30/min |
| GET | /bits/gantt | Global gantt view | JWT | 30/min |
| GET | /bits/gantt/:chainyId | Chainy-scoped gantt view | JWT | 30/min |
| GET | /bits/by-chain/:chainId | List bits by chain | JWT | 60/min |
| GET | /bits/:id | Get a single bit | JWT | 60/min |
| POST | /bits | Create a bit | JWT | 30/min |
| POST | /bits/insert-all | Bulk create bits | JWT | 10/min |
| PATCH | /bits/:id | Update a bit | JWT | 30/min |
| DELETE | /bits/:id | Delete a bit | JWT | 30/min |
| POST | /bits/:id/execute | Execute a bit through AI | JWT + Entitlement | 30/min |
Create Bit
Request
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Bit title (1-500 chars) |
chainId | string | Yes | Parent chain ID |
description | string | No | Detailed description |
priority | string | No | low, medium, high, urgent |
dueDate | string | No | ISO 8601 due date |
estimatedMinutes | number | No | Estimated time in minutes |
parentBitId | string | No | Parent bit ID for nesting |
tags | string[] | No | Array of tag strings |
Response
{
"data": {
"id": "cm5bit001",
"title": "Study verb conjugations - present tense",
"chainId": "$CHAIN_ID",
"description": "Focus on regular -ar, -er, -ir verb conjugations",
"priority": "high",
"status": "pending",
"dueDate": "2026-03-18T23:59:59.000Z",
"estimatedMinutes": 30,
"parentBitId": null,
"tags": ["grammar", "verbs"],
"createdAt": "2026-03-17T11:00:00.000Z",
"updatedAt": "2026-03-17T11:00:00.000Z"
}
}Code Examples
Use the id from Create Chain's response (data.id) as $CHAIN_ID.
curl -X POST https://api.chainabit.com/api/v1/bits \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Study verb conjugations - present tense",
"chainId": "'"$CHAIN_ID"'",
"description": "Focus on regular -ar, -er, -ir verb conjugations",
"priority": "high",
"dueDate": "2026-03-18T23:59:59Z",
"estimatedMinutes": 30,
"tags": ["grammar", "verbs"]
}'const BASE_URL = process.env.BASE_URL;
const TOKEN = process.env.TOKEN;
const chainId = process.env.CHAIN_ID; // from a chain lookup / create-chain response
const response = await fetch(`${BASE_URL}/bits`, {
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Study verb conjugations - present tense",
chainId,
description: "Focus on regular -ar, -er, -ir verb conjugations",
priority: "high",
dueDate: "2026-03-18T23:59:59Z",
estimatedMinutes: 30,
tags: ["grammar", "verbs"],
}),
});
const { data } = await response.json();import requests, os
chain_id = os.environ["CHAIN_ID"] # from a chain lookup / create_chain()'s response
response = requests.post(
f"{os.environ['BASE_URL']}/bits",
headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
json={
"title": "Study verb conjugations - present tense",
"chainId": chain_id,
"description": "Focus on regular -ar, -er, -ir verb conjugations",
"priority": "high",
"dueDate": "2026-03-18T23:59:59Z",
"estimatedMinutes": 30,
"tags": ["grammar", "verbs"],
},
)
data = response.json()["data"]Bulk Create Bits
Request
Reuses the same $CHAIN_ID as Create Bit above — all bits in one bulk insert go to the same chain.
Response
{
"data": [
{ "id": "cm5bit002", "title": "Practice listening comprehension", "status": "pending" },
{ "id": "cm5bit003", "title": "Write 5 sentences in Spanish", "status": "pending" },
{ "id": "cm5bit004", "title": "Read a news article in Spanish", "status": "pending" }
],
"meta": { "inserted": 3 }
}Code Examples
curl -X POST https://api.chainabit.com/api/v1/bits/insert-all \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bits": [
{ "title": "Practice listening comprehension", "chainId": "'"$CHAIN_ID"'" },
{ "title": "Write 5 sentences in Spanish", "chainId": "'"$CHAIN_ID"'" },
{ "title": "Read a news article in Spanish", "chainId": "'"$CHAIN_ID"'" }
]
}'const BASE_URL = process.env.BASE_URL;
const TOKEN = process.env.TOKEN;
const chainId = process.env.CHAIN_ID; // from a chain lookup / create-chain response
const response = await fetch(`${BASE_URL}/bits/insert-all`, {
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
bits: [
{ title: "Practice listening comprehension", chainId },
{ title: "Write 5 sentences in Spanish", chainId },
{ title: "Read a news article in Spanish", chainId },
],
}),
});
const { data } = await response.json();import requests, os
chain_id = os.environ["CHAIN_ID"] # from a chain lookup / create_chain()'s response
response = requests.post(
f"{os.environ['BASE_URL']}/bits/insert-all",
headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
json={
"bits": [
{"title": "Practice listening comprehension", "chainId": chain_id},
{"title": "Write 5 sentences in Spanish", "chainId": chain_id},
{"title": "Read a news article in Spanish", "chainId": chain_id},
]
},
)
data = response.json()["data"]Tree View
Request
- Headers:
Authorization: Bearer <token>
Response
{
"data": [
{
"id": "cm5bit001",
"title": "Study verb conjugations - present tense",
"children": [
{ "id": "cm5bit005", "title": "Regular -ar verbs", "children": [] }
]
}
]
}Code Examples
curl https://api.chainabit.com/api/v1/bits/tree \
-H "Authorization: Bearer $TOKEN"const BASE_URL = process.env.BASE_URL;
const TOKEN = process.env.TOKEN;
const response = await fetch(`${BASE_URL}/bits/tree`, {
headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data } = await response.json();import requests, os
response = requests.get(
f"{os.environ['BASE_URL']}/bits/tree",
headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
)
data = response.json()["data"]Matrix View
Request
- Headers:
Authorization: Bearer <token>
Response
{
"data": {
"urgent_important": [
{ "id": "cm5bit001", "title": "Study verb conjugations - present tense" }
],
"not_urgent_important": [],
"urgent_not_important": [],
"not_urgent_not_important": []
}
}Code Examples
curl https://api.chainabit.com/api/v1/bits/matrix \
-H "Authorization: Bearer $TOKEN"const BASE_URL = process.env.BASE_URL;
const TOKEN = process.env.TOKEN;
const response = await fetch(`${BASE_URL}/bits/matrix`, {
headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data } = await response.json();import requests, os
response = requests.get(
f"{os.environ['BASE_URL']}/bits/matrix",
headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
)
data = response.json()["data"]Calendar View
Request
- Headers:
Authorization: Bearer <token>
Response
{
"data": {
"2026-03-17": [
{ "id": "cm5bit001", "title": "Study verb conjugations - present tense", "dueDate": "2026-03-18T23:59:59.000Z" }
],
"2026-03-18": []
}
}Code Examples
curl https://api.chainabit.com/api/v1/bits/calendar \
-H "Authorization: Bearer $TOKEN"const BASE_URL = process.env.BASE_URL;
const TOKEN = process.env.TOKEN;
const response = await fetch(`${BASE_URL}/bits/calendar`, {
headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data } = await response.json();import requests, os
response = requests.get(
f"{os.environ['BASE_URL']}/bits/calendar",
headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
)
data = response.json()["data"]Gantt View
Request
- Headers:
Authorization: Bearer <token>
The chainy-scoped variant takes a chainyId path param — use the id from Create Chainy's response (data.id) as $CHAINY_ID.
Response
{
"data": [
{
"id": "cm5bit001",
"title": "Study verb conjugations - present tense",
"startDate": "2026-03-17T00:00:00.000Z",
"dueDate": "2026-03-18T23:59:59.000Z",
"dependencies": []
}
]
}Code Examples
# Global gantt
curl https://api.chainabit.com/api/v1/bits/gantt \
-H "Authorization: Bearer $TOKEN"
# Chainy-scoped gantt
curl https://api.chainabit.com/api/v1/bits/gantt/$CHAINY_ID \
-H "Authorization: Bearer $TOKEN"const BASE_URL = process.env.BASE_URL;
const TOKEN = process.env.TOKEN;
const chainyId = process.env.CHAINY_ID; // from a chainy lookup / create-chainy response
// Global gantt
const response = await fetch(`${BASE_URL}/bits/gantt`, {
headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data } = await response.json();
// Chainy-scoped gantt
const scopedResponse = await fetch(`${BASE_URL}/bits/gantt/${chainyId}`, {
headers: { Authorization: `Bearer ${TOKEN}` },
});import requests, os
headers = {"Authorization": f"Bearer {os.environ['TOKEN']}"}
chainy_id = os.environ["CHAINY_ID"] # from a chainy lookup / create_chainy()'s response
# Global gantt
response = requests.get(f"{os.environ['BASE_URL']}/bits/gantt", headers=headers)
data = response.json()["data"]
# Chainy-scoped gantt
scoped = requests.get(f"{os.environ['BASE_URL']}/bits/gantt/{chainy_id}", headers=headers)Bit Completion Events
Track completion of bits over time. Each event records when a bit was marked as done.
Endpoints
| Method | Path | Description | Auth | Rate Limit |
|---|---|---|---|---|
| GET | /bits/:bitId/events | List completion events for a bit | JWT | 60/min |
| GET | /chains/:chainId/events | List completion events for a chain | JWT | 60/min |
| POST | /bits/:bitId/events | Record a completion event | JWT | 30/min |
Record Completion Event
Request
| Field | Type | Required | Description |
|---|---|---|---|
completedAt | string | No | ISO 8601 timestamp |
notes | string | No | Optional completion notes |
durationMinutes | number | No | Actual time spent in minutes |
Response
{
"data": {
"id": "cm5evt001",
"bitId": "$BIT_ID",
"completedAt": "2026-03-17T14:30:00.000Z",
"notes": "Completed all present tense conjugations for -ar verbs",
"durationMinutes": 25,
"createdAt": "2026-03-17T14:30:00.000Z"
}
}Code Examples
Use the id from Create Bit's response (data.id) as $BIT_ID.
curl -X POST https://api.chainabit.com/api/v1/bits/$BIT_ID/events \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"completedAt": "2026-03-17T14:30:00Z",
"notes": "Completed all present tense conjugations for -ar verbs",
"durationMinutes": 25
}'const BASE_URL = process.env.BASE_URL;
const TOKEN = process.env.TOKEN;
const bitId = process.env.BIT_ID; // from a bit lookup / create-bit response
const response = await fetch(`${BASE_URL}/bits/${bitId}/events`, {
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
completedAt: "2026-03-17T14:30:00Z",
notes: "Completed all present tense conjugations for -ar verbs",
durationMinutes: 25,
}),
});
const { data } = await response.json();import requests, os
bit_id = os.environ["BIT_ID"] # from a bit lookup / create_bit()'s response
response = requests.post(
f"{os.environ['BASE_URL']}/bits/{bit_id}/events",
headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
json={
"completedAt": "2026-03-17T14:30:00Z",
"notes": "Completed all present tense conjugations for -ar verbs",
"durationMinutes": 25,
},
)
data = response.json()["data"]List Events for a Chain
Request
Same $CHAIN_ID as in Create Bit above.
Response
{
"data": [
{
"id": "cm5evt001",
"bitId": "$BIT_ID",
"completedAt": "2026-03-17T14:30:00.000Z",
"durationMinutes": 25
}
],
"meta": { "total": 1 }
}Code Examples
curl https://api.chainabit.com/api/v1/chains/$CHAIN_ID/events \
-H "Authorization: Bearer $TOKEN"const BASE_URL = process.env.BASE_URL;
const TOKEN = process.env.TOKEN;
const chainId = process.env.CHAIN_ID; // from a chain lookup / create-chain response
const response = await fetch(`${BASE_URL}/chains/${chainId}/events`, {
headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data } = await response.json();import requests, os
chain_id = os.environ["CHAIN_ID"] # from a chain lookup / create_chain()'s response
response = requests.get(
f"{os.environ['BASE_URL']}/chains/{chain_id}/events",
headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
)
data = response.json()["data"]Bit Execution Profiles
Execution profiles define how a bit should be executed.
Endpoints
| Method | Path | Description | Auth | Rate Limit |
|---|---|---|---|---|
| GET | /bits/:bitId/executions | List execution profiles | JWT | 60/min |
| POST | /bits/:bitId/executions | Create an execution profile | JWT | 30/min |
| PATCH | /bits/:bitId/executions/:id | Update a profile | JWT | 30/min |
| DELETE | /bits/:bitId/executions/:id | Delete a profile | JWT | 30/min |
Create Execution Profile
Request
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Profile type: timer, pomodoro, focus, freeform |
durationMinutes | number | No | Duration in minutes |
breakMinutes | number | No | Break duration |
rounds | number | No | Number of rounds |
Same $BIT_ID as in Record Completion Event above.
Response
{
"data": {
"id": "cm5exec01",
"bitId": "$BIT_ID",
"type": "pomodoro",
"durationMinutes": 25,
"breakMinutes": 5,
"rounds": 4,
"createdAt": "2026-03-17T11:30:00.000Z"
}
}Code Examples
curl -X POST https://api.chainabit.com/api/v1/bits/$BIT_ID/executions \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "pomodoro",
"durationMinutes": 25,
"breakMinutes": 5,
"rounds": 4
}'const BASE_URL = process.env.BASE_URL;
const TOKEN = process.env.TOKEN;
const bitId = process.env.BIT_ID; // from a bit lookup / create-bit response
const response = await fetch(`${BASE_URL}/bits/${bitId}/executions`, {
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
type: "pomodoro",
durationMinutes: 25,
breakMinutes: 5,
rounds: 4,
}),
});
const { data } = await response.json();import requests, os
bit_id = os.environ["BIT_ID"] # from a bit lookup / create_bit()'s response
response = requests.post(
f"{os.environ['BASE_URL']}/bits/{bit_id}/executions",
headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
json={"type": "pomodoro", "durationMinutes": 25, "breakMinutes": 5, "rounds": 4},
)
data = response.json()["data"]Bit Relations
Define dependencies and relationships between bits.
Endpoints
| Method | Path | Description | Auth | Rate Limit |
|---|---|---|---|---|
| GET | /bits/:bitId/relations | List relations (supports ?relationType) | JWT | 60/min |
| POST | /bits/:bitId/relations/connect | Connect two bits | JWT | 30/min |
| POST | /bits/:bitId/relations/disconnect | Disconnect two bits | JWT | 30/min |
| DELETE | /bits/:bitId/relations/:id | Delete a relation | JWT | 30/min |
Connect Two Bits
Request
| Field | Type | Required | Description |
|---|---|---|---|
targetBitId | string | Yes | The bit to connect to |
relationType | string | Yes | blocks, blocked_by, relates_to, duplicates |
$BIT_ID is the source bit (see Create Bit); $TARGET_BIT_ID is the id of the other bit you want to connect it to.
Response
{
"data": {
"id": "cm5rel001",
"sourceBitId": "$BIT_ID",
"targetBitId": "$TARGET_BIT_ID",
"relationType": "blocks",
"createdAt": "2026-03-17T12:00:00.000Z"
}
}Code Examples
curl -X POST https://api.chainabit.com/api/v1/bits/$BIT_ID/relations/connect \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"targetBitId": "'"$TARGET_BIT_ID"'",
"relationType": "blocks"
}'const BASE_URL = process.env.BASE_URL;
const TOKEN = process.env.TOKEN;
const bitId = process.env.BIT_ID; // the source bit, from a bit lookup / create-bit response
const targetBitId = process.env.TARGET_BIT_ID; // the bit to connect it to
const response = await fetch(`${BASE_URL}/bits/${bitId}/relations/connect`, {
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
targetBitId,
relationType: "blocks",
}),
});
const { data } = await response.json();import requests, os
bit_id = os.environ["BIT_ID"] # the source bit, from a bit lookup / create_bit()'s response
target_bit_id = os.environ["TARGET_BIT_ID"] # the bit to connect it to
response = requests.post(
f"{os.environ['BASE_URL']}/bits/{bit_id}/relations/connect",
headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
json={"targetBitId": target_bit_id, "relationType": "blocks"},
)
data = response.json()["data"]