AI Suggestions
AI-generated suggestions for improving productivity workflows.
Endpoints
| Method | Path | Description | Auth | Rate Limit |
|---|---|---|---|---|
| GET | /ai/suggestions | List suggestions (filterable) | JWT + Entitlement | 60/min |
| GET | /ai/suggestions/:id | Get a suggestion | JWT + Entitlement | 60/min |
| POST | /ai/suggestions | Create a suggestion | JWT + Entitlement | 10/min |
| PATCH | /ai/suggestions/:id/accept | Accept a suggestion | JWT + Entitlement | 30/min |
| PATCH | /ai/suggestions/:id/dismiss | Dismiss a suggestion | JWT + Entitlement | 30/min |
GET /ai/suggestions
List suggestions with optional filters.
Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 60/min
Request
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter: pending, accepted, dismissed |
targetType | string | No | Filter: chain, chainy, bit, schedule |
targetId | string | No | Filter by target entity ID |
source | string | No | Filter by source: chao, twin, manual |
limit | number | No | Items per page |
offset | number | No | Pagination offset |
Response
Response Example
{
"data": [
{
"id": "cm5sug01",
"targetType": "chain",
"targetId": "cm5chain01",
"type": "schedule_change",
"content": "Consider shifting your vocabulary practice to mornings. Your completion rate is 40% higher before noon.",
"status": "pending",
"payload": {
"suggestedTime": "08:00",
"reasoning": "completion_rate_analysis"
},
"createdAt": "2026-03-17T10:00:00.000Z"
}
],
"meta": {
"total": 1,
"limit": 10,
"offset": 0
}
}Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Suggestion ID |
targetType | string | Target entity type |
targetId | string | Target entity ID |
type | string | Suggestion type |
content | string | Human-readable text |
status | string | pending, accepted, dismissed |
payload | object | null | Structured suggestion data |
source | string | null | Suggestion source (chao, twin, manual) |
analysisId | string | null | Originating analysis ID (for Chao-generated proposals) |
createdAt | string | ISO 8601 |
Code Examples
curl "https://api.chainabit.com/api/v1/ai/suggestions?status=pending&targetType=chain&limit=10" \
-H "Authorization: Bearer $TOKEN"const params = new URLSearchParams({
status: "pending",
targetType: "chain",
limit: "10",
});
const res = await fetch(`${BASE_URL}/ai/suggestions?${params}`, {
headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data, meta } = await res.json();import requests
res = requests.get(
f"{BASE_URL}/ai/suggestions",
headers={"Authorization": f"Bearer {TOKEN}"},
params={"status": "pending", "targetType": "chain", "limit": 10},
)
body = res.json()GET /ai/suggestions/:id
Get details of a specific suggestion.
Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 60/min
Request
Response
Response Example
{
"data": {
"id": "cm5sug01",
"targetType": "chain",
"targetId": "cm5chain01",
"type": "schedule_change",
"content": "Consider shifting your vocabulary practice to mornings. Your completion rate is 40% higher before noon.",
"status": "pending",
"payload": {
"suggestedTime": "08:00",
"reasoning": "completion_rate_analysis"
},
"createdAt": "2026-03-17T10:00:00.000Z"
}
}Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Suggestion ID |
targetType | string | Target entity type |
targetId | string | Target entity ID |
type | string | Suggestion type |
content | string | Human-readable text |
status | string | pending, accepted, dismissed |
payload | object | null | Structured suggestion data |
source | string | null | Suggestion source (chao, twin, manual) |
analysisId | string | null | Originating analysis ID (for Chao-generated proposals) |
createdAt | string | ISO 8601 |
Code Examples
Replace
$SUGGESTION_IDbelow with theidfrom a list or create response.
curl https://api.chainabit.com/api/v1/ai/suggestions/$SUGGESTION_ID \
-H "Authorization: Bearer $TOKEN"const SUGGESTION_ID = process.env.SUGGESTION_ID; // id from a list or create response
const res = await fetch(`${BASE_URL}/ai/suggestions/${SUGGESTION_ID}`, {
headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data } = await res.json();import os
import requests
suggestion_id = os.environ["SUGGESTION_ID"] # id from a list or create response
res = requests.get(
f"{BASE_URL}/ai/suggestions/{suggestion_id}",
headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]POST /ai/suggestions
Create a new AI suggestion for a target entity.
Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 10/min
Request
Request Body
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
targetType | string | Yes | chain, chainy, bit, schedule | Target entity type |
targetId | string | Yes | Valid entity ID | Target entity ID |
type | string | Yes | schedule_change, bit_creation, chain_adjustment | Suggestion type |
content | string | Yes | Non-empty | Human-readable suggestion text |
payload | object | No | — | Structured data for the suggestion |
source | string | No | chao, twin, manual | Suggestion source |
analysisId | string | No | Valid UUID | UUID linking to the originating analysis |
targetIdmust be theidof an existing chain, chainy, bit, or schedule (matchingtargetType) — get it from that resource's own create/list response.$TARGET_IDbelow is a placeholder for that value.
Response
Response Example
{
"data": {
"id": "cm5sug01",
"targetType": "chain",
"targetId": "cm5chain01",
"type": "schedule_change",
"content": "Consider shifting your vocabulary practice to mornings. Your completion rate is 40% higher before noon.",
"status": "pending",
"payload": {
"suggestedTime": "08:00",
"reasoning": "completion_rate_analysis"
},
"createdAt": "2026-03-17T10:00:00.000Z"
}
}Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Suggestion ID |
targetType | string | Target entity type |
targetId | string | Target entity ID |
type | string | Suggestion type |
content | string | Human-readable text |
status | string | pending, accepted, dismissed |
payload | object | null | Structured suggestion data |
source | string | null | Suggestion source (chao, twin, manual) |
analysisId | string | null | Originating analysis ID (for Chao-generated proposals) |
createdAt | string | ISO 8601 |
Code Examples
curl -X POST https://api.chainabit.com/api/v1/ai/suggestions \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"targetType": "chain",
"targetId": "'"$TARGET_ID"'",
"type": "schedule_change",
"content": "Consider shifting your vocabulary practice to mornings. Your completion rate is 40% higher before noon.",
"payload": {
"suggestedTime": "08:00",
"reasoning": "completion_rate_analysis"
}
}'const targetId = process.env.TARGET_ID; // id of the chain/chainy/bit/schedule this suggestion targets
const res = await fetch(`${BASE_URL}/ai/suggestions`, {
method: "POST",
headers: {
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
targetType: "chain",
targetId,
type: "schedule_change",
content:
"Consider shifting your vocabulary practice to mornings. Your completion rate is 40% higher before noon.",
payload: {
suggestedTime: "08:00",
reasoning: "completion_rate_analysis",
},
}),
});
const { data } = await res.json();import os
import requests
target_id = os.environ["TARGET_ID"] # id of the chain/chainy/bit/schedule this suggestion targets
res = requests.post(
f"{BASE_URL}/ai/suggestions",
headers={
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
},
json={
"targetType": "chain",
"targetId": target_id,
"type": "schedule_change",
"content": "Consider shifting your vocabulary practice to mornings. Your completion rate is 40% higher before noon.",
"payload": {
"suggestedTime": "08:00",
"reasoning": "completion_rate_analysis",
},
},
)
data = res.json()["data"]PATCH /ai/suggestions/:id/accept
Accept a pending suggestion.
Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 30/min
Request
Response
Response Example
{
"data": {
"id": "cm5sug01",
"status": "accepted",
"acceptedAt": "2026-03-17T11:00:00.000Z"
}
}Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Suggestion ID |
status | string | Always accepted |
acceptedAt | string | ISO 8601 timestamp of acceptance |
Code Examples
Replace
$SUGGESTION_IDbelow with theidfrom a list or create response.
curl -X PATCH https://api.chainabit.com/api/v1/ai/suggestions/$SUGGESTION_ID/accept \
-H "Authorization: Bearer $TOKEN"const SUGGESTION_ID = process.env.SUGGESTION_ID; // id from a list or create response
const res = await fetch(`${BASE_URL}/ai/suggestions/${SUGGESTION_ID}/accept`, {
method: "PATCH",
headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data } = await res.json();import os
import requests
suggestion_id = os.environ["SUGGESTION_ID"] # id from a list or create response
res = requests.patch(
f"{BASE_URL}/ai/suggestions/{suggestion_id}/accept",
headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]PATCH /ai/suggestions/:id/dismiss
Dismiss a pending suggestion.
Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 30/min
Request
Response
Response Example
{
"data": {
"id": "cm5sug01",
"status": "dismissed",
"dismissedAt": "2026-03-17T11:00:00.000Z"
}
}Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Suggestion ID |
status | string | Always dismissed |
dismissedAt | string | ISO 8601 timestamp of dismissal |
Code Examples
Replace
$SUGGESTION_IDbelow with theidfrom a list or create response.
curl -X PATCH https://api.chainabit.com/api/v1/ai/suggestions/$SUGGESTION_ID/dismiss \
-H "Authorization: Bearer $TOKEN"const SUGGESTION_ID = process.env.SUGGESTION_ID; // id from a list or create response
const res = await fetch(`${BASE_URL}/ai/suggestions/${SUGGESTION_ID}/dismiss`, {
method: "PATCH",
headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data } = await res.json();import os
import requests
suggestion_id = os.environ["SUGGESTION_ID"] # id from a list or create response
res = requests.patch(
f"{BASE_URL}/ai/suggestions/{suggestion_id}/dismiss",
headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]Chao Proposals
Chao automatically generates suggestions (proposals) when analyses detect actionable findings. These proposals provide concrete next steps derived from analysis results.
- All Chao proposals have
source: "chao"andstatus: "pending" - Chao never auto-applies suggestions — the user must explicitly accept via
PATCH /ai/suggestions/:id/accept - Proposal types generated by Chao:
create_bit,reschedule,prioritize,decompose,summarize - Maximum 3 proposals per analysis run