Skip to content

Chainy Analysis

Analyse a Chainy's chain completion data to generate progress summaries, pattern insights, health scores, and recovery plans. Also exposes a task decomposition endpoint that breaks a free-text description into ordered sub-bits.

Endpoints

MethodPathDescriptionAuthRate Limit
POST/ai/chainy-analysisTrigger analysis for a ChainyJWT + Entitlement10/min
GET/ai/chainy-analysis/:chainyIdList past analyses for a ChainyJWT + Entitlement60/min
POST/ai/chainy-analysis/bit-decompositionDecompose a task into sub-bitsJWT + Entitlement10/min

POST /ai/chainy-analysis

Trigger an AI analysis of a Chainy. Results are stored and retrievable via the GET endpoint.

Request

  • Auth: JWT Bearer token + active AI entitlement required
  • chainyId must be the id of an existing Chainy — e.g. from Create Chainy, shown below as $CHAINY_ID.
Request Body
FieldTypeRequiredConstraintsDescription
chainyIdstringYesValid UUIDChainy to analyse
analysisTypestringYesSee table belowType of analysis to run
Analysis Types
analysisTypeDescription
progressSummary stats: total chains, active count, total completions, average streak
patternsTemporal patterns: completion velocity, recent activity, chain distribution
recommendationsTyped recommendation list (streak_recovery, get_started, maintain)
decompositionChain listing with status for decomposition planning
chainy_healthComposite health score (0–100): active chain ratio, streak health, velocity, fragmentation
continuityAt-risk chain detection: chains at risk of streak break, broken, and strong performers
blockerStall detection: chains with zero or declining progress
routineTime-of-day and day-of-week completion pattern analysis
focusAttention distribution: neglected vs over-served chains
recoveryStructured recovery plan for broken streaks with prioritised next actions

Response

Response Example
json
{
  "data": {
    "id": "cm9analysis01",
    "chainyId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "analysisType": "chainy_health",
    "result": {
      "healthScore": 74,
      "signals": ["strong_streaks", "low_fragmentation"],
      "breakdown": {
        "activeChainRatio": 0.8,
        "streakHealth": 0.9,
        "velocity": 0.6,
        "fragmentation": 0.2
      }
    },
    "createdAt": "2026-05-22T10:00:00.000Z"
  }
}

Code Examples

bash
curl -X POST "$BASE_URL/ai/chainy-analysis" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "chainyId": "'"$CHAINY_ID"'",
    "analysisType": "chainy_health"
  }'
javascript
const chainyId = process.env.CHAINY_ID; // id of the Chainy to analyze

const res = await fetch(`${BASE_URL}/ai/chainy-analysis`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    chainyId,
    analysisType: "chainy_health",
  }),
});
const { data } = await res.json();
python
import os
import requests

chainy_id = os.environ["CHAINY_ID"]  # id of the Chainy to analyze

res = requests.post(
    f"{BASE_URL}/ai/chainy-analysis",
    headers={"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"},
    json={
        "chainyId": chainy_id,
        "analysisType": "chainy_health",
    },
)
data = res.json()["data"]

GET /ai/chainy-analysis/:chainyId

List past analyses for a specific Chainy. Scoped to the authenticated user.

Request

  • Auth: JWT Bearer token + active AI entitlement required
  • Path params: chainyId — use the same Chainy id you analysed above (or any Chainy's id from Create Chainy) as $CHAINY_ID

Response

Response Example
json
{
  "data": [
    {
      "id": "cm9analysis01",
      "chainyId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "analysisType": "chainy_health",
      "result": { "healthScore": 74 },
      "createdAt": "2026-05-22T10:00:00.000Z"
    }
  ]
}

Code Examples

bash
curl "$BASE_URL/ai/chainy-analysis/$CHAINY_ID" \
  -H "Authorization: Bearer $TOKEN"
javascript
const chainyId = process.env.CHAINY_ID; // id of the Chainy to list analyses for
const res = await fetch(`${BASE_URL}/ai/chainy-analysis/${chainyId}`, {
  headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data } = await res.json();
python
import os
import requests

chainy_id = os.environ["CHAINY_ID"]  # id of the Chainy to list analyses for
res = requests.get(
    f"{BASE_URL}/ai/chainy-analysis/{chainy_id}",
    headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]

POST /ai/chainy-analysis/bit-decomposition

Break a free-text task description into an ordered list of smaller, actionable sub-bits. Optionally scoped to an existing bit for further decomposition.

Request

  • Auth: JWT Bearer token + active AI entitlement required
  • chainId must be the id of an existing chain — e.g. from Create Chain, shown below as $CHAIN_ID.
Request Body
FieldTypeRequiredConstraintsDescription
chainIdstringYesValid UUIDChain that provides context for decomposition
descriptionstringYesmax 2000 charsTask description to decompose
bitIdstringNoValid UUIDExisting bit to decompose further

Response

Response Example
json
{
  "data": {
    "suggestedBits": [
      { "title": "Choose CI/CD provider", "order": 1, "estimatedMinutes": 30 },
      { "title": "Configure build pipeline", "order": 2, "estimatedMinutes": 60 },
      { "title": "Add deployment stage", "order": 3, "estimatedMinutes": 45 },
      { "title": "Set up environment secrets", "order": 4, "estimatedMinutes": 20 },
      { "title": "Run first end-to-end deploy", "order": 5, "estimatedMinutes": 30 }
    ]
  }
}
Response Fields
FieldTypeDescription
suggestedBitsobject[]Ordered list of suggested sub-tasks
suggestedBits[].titlestringSub-task title
suggestedBits[].descriptionstring | undefinedOptional elaboration
suggestedBits[].estimatedMinutesnumber | undefinedTime estimate
suggestedBits[].ordernumberPosition in the sequence

Code Examples

bash
curl -X POST "$BASE_URL/ai/chainy-analysis/bit-decomposition" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "chainId": "'"$CHAIN_ID"'",
    "description": "Set up CI/CD pipeline for the mobile app"
  }'
javascript
const chainId = process.env.CHAIN_ID; // id of the chain that provides decomposition context

const res = await fetch(`${BASE_URL}/ai/chainy-analysis/bit-decomposition`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    chainId,
    description: "Set up CI/CD pipeline for the mobile app",
  }),
});
const { data } = await res.json();
python
import os
import requests

chain_id = os.environ["CHAIN_ID"]  # id of the chain that provides decomposition context

res = requests.post(
    f"{BASE_URL}/ai/chainy-analysis/bit-decomposition",
    headers={"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"},
    json={
        "chainId": chain_id,
        "description": "Set up CI/CD pipeline for the mobile app",
    },
)
data = res.json()["data"]

Error Responses

StatusCodeWhen
400VALIDATION_FAILEDMissing required fields or invalid UUID
403FORBIDDENChainy or Chain does not belong to your account
503SERVICE_UNAVAILABLENo AI provider available

Built with purpose.