Skip to content

AI Sessions ​

Sessions are persistent conversation contexts for multi-turn AI interactions. Sessions support archiving and pinning for organization, and are automatically purged 30 days after being ended to comply with AI provider data retention policies.

Session Lifecycle Walkthrough ​

  1. POST /ai/sessions to create a session (set assistantType, optional metadata, and the primary context scope you need).
  2. Persist the session.id and poll GET /ai/sessions/:id to render the session title, status, and last activity.
  3. Use PATCH /ai/sessions/:id/pin / archive / unpin / unarchive for the organization workflow you want, then call DELETE /ai/sessions/:id when the conversation is over.
  4. Keep session IDs to load history (GET /ai/sessions), resume SSE streams, or reference messageCount in your UI.
javascript
const chainyId = process.env.CHAINY_ID; // id of the Chainy this session is scoped to

const manageSession = async () => {
  const sessionRes = await fetch(`${BASE_URL}/ai/sessions`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      title: "Chainabit onboarding",
      assistantType: "chao",
      primaryContextType: "chainy",
      primaryContextId: chainyId,
    }),
  });
  const session = (await sessionRes.json()).data;

  await fetch(`${BASE_URL}/ai/sessions/${session.id}/pin`, {
    method: "PATCH",
    headers: { Authorization: `Bearer ${TOKEN}` },
  });

  const refreshed = await fetch(
    `${BASE_URL}/ai/sessions/${session.id}`,
    { headers: { Authorization: `Bearer ${TOKEN}` } }
  );
  console.log("Session status:", (await refreshed.json()).data.status);
};

Endpoints ​

MethodPathDescriptionAuthRate Limit
GET/ai/sessionsList sessionsJWT + Entitlement60/min
POST/ai/sessionsCreate a sessionJWT + Entitlement20/min
GET/ai/sessions/:idGet a sessionJWT + Entitlement60/min
DELETE/ai/sessions/:idEnd a sessionJWT + Entitlement30/min
PATCH/ai/sessions/:id/archiveArchive a sessionJWT + Entitlement30/min
PATCH/ai/sessions/:id/unarchiveRestore an archived sessionJWT + Entitlement30/min
PATCH/ai/sessions/:id/pinPin a sessionJWT + Entitlement60/min
PATCH/ai/sessions/:id/unpinUnpin a sessionJWT + Entitlement60/min
POST/workspaces/:workspaceId/ai/sessions/:sessionId/shareCreate or reactivate a share link (public unless noIndex is set)JWT + Entitlement20/min
PATCH/workspaces/:workspaceId/ai/sessions/:sessionId/shareSwitch an active share between public and link onlyJWT + Entitlement20/min
DELETE/workspaces/:workspaceId/ai/sessions/:sessionId/shareRevoke a share linkJWT + Entitlement20/min
GET/cs/:urlShortResolve a shared session by short URLNone (public)60/60s

GET /ai/sessions ​

Description ​

List AI sessions for the authenticated user. Returns active sessions by default. Pass ?status=archived to list archived sessions. Results are offset-paginated and can be searched with q.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 60/min

Request ​

Query Parameters ​
ParameterTypeDescription
limitintegerNumber of sessions to return. Defaults to 20, max 50.
offsetintegerNumber of sessions to skip. Defaults to 0.
status"active" | "archived"Filter by session status. Defaults to active.
chainyIdstring (uuid)Optional. Filter to sessions associated with a specific Chainy (AI personality).
qstringOptional. Search session titles or date-like session timestamps. Max 200 characters.

Response ​

Response Example ​
json
{
  "data": [
    {
      "id": "cm5sess01",
      "title": "Spanish Learning Coach",
      "status": "active",
      "messageCount": 5,
      "pinnedAt": "2026-03-17T09:00:00.000Z",
      "archivedAt": null,
      "createdAt": "2026-03-17T10:00:00.000Z",
      "updatedAt": "2026-03-17T11:00:00.000Z"
    }
  ],
  "meta": {
    "limit": 20,
    "offset": 0,
    "total": 1,
    "totalCount": 1,
    "hasNextPage": false
  }
}
Response Fields ​
FieldTypeDescription
idstringSession ID
titlestring | nullSession title
statusstringactive or archived
messageCountnumberNumber of messages in the session
pinnedAtstring | nullISO 8601 timestamp when pinned, or null
archivedAtstring | nullISO 8601 timestamp when archived, or null
createdAtstringISO 8601
updatedAtstringISO 8601

Code Examples ​

Use the id of one of your Chainies (AI personalities) as $CHAINY_ID in the filter example below.

bash
curl "https://api.chainabit.com/api/v1/ai/sessions?limit=20&offset=0" \
  -H "Authorization: Bearer $TOKEN"

# Archived sessions:
curl "https://api.chainabit.com/api/v1/ai/sessions?status=archived" \
  -H "Authorization: Bearer $TOKEN"

# Filter by Chainy (AI personality):
curl "https://api.chainabit.com/api/v1/ai/sessions?chainyId=$CHAINY_ID" \
  -H "Authorization: Bearer $TOKEN"

# Search sessions:
curl "https://api.chainabit.com/api/v1/ai/sessions?q=weekly%20planning" \
  -H "Authorization: Bearer $TOKEN"
javascript
const chainyId = process.env.CHAINY_ID; // id of the Chainy to filter by

const res = await fetch(`${BASE_URL}/ai/sessions?limit=20&offset=0`, {
  headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data, meta } = await res.json();

// Archived sessions:
const archived = await fetch(`${BASE_URL}/ai/sessions?status=archived`, {
  headers: { Authorization: `Bearer ${TOKEN}` },
});

// Filter by Chainy:
const chainySpecific = await fetch(
  `${BASE_URL}/ai/sessions?chainyId=${chainyId}`,
  { headers: { Authorization: `Bearer ${TOKEN}` } }
);

// Search by title or date:
const search = await fetch(`${BASE_URL}/ai/sessions?q=weekly%20planning`, {
  headers: { Authorization: `Bearer ${TOKEN}` },
});
python
import os
import requests

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

res = requests.get(
    f"{BASE_URL}/ai/sessions",
    params={"limit": 20, "offset": 0},
    headers={"Authorization": f"Bearer {TOKEN}"},
)
body = res.json()

# Archived sessions:
archived = requests.get(
    f"{BASE_URL}/ai/sessions",
    params={"status": "archived"},
    headers={"Authorization": f"Bearer {TOKEN}"},
)

# Filter by Chainy:
chainy_specific = requests.get(
    f"{BASE_URL}/ai/sessions",
    params={"chainyId": chainy_id},
    headers={"Authorization": f"Bearer {TOKEN}"},
)

search = requests.get(
    f"{BASE_URL}/ai/sessions",
    params={"q": "weekly planning"},
    headers={"Authorization": f"Bearer {TOKEN}"},
)

POST /ai/sessions ​

Description ​

Create a new AI session.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 20/min

Request ​

Request Body ​

Unknown properties are rejected. The request body accepts only the fields below.

FieldTypeRequiredConstraintsDescription
titlestringNoMax 120 charsSession title
assistantTypestringNo"chat" | "chao"Session assistant type. Set to "chao" for Chao behavioral advisor sessions. Default: "chat".
assistantPresetstringNo—Named assistant preset to apply to this session
modelstringNo—Exact active model_key to use, e.g. gemini-2.5-flash
providerstringNoMax 64 charsPreferred provider key. Falls back to another active provider if unavailable.
effortModestringNo"basic" | "thinking" | "pro"High-level routing preference; the orchestrator picks a compatible model.
modestringNo"auto" | "approval" | "plan"Tool execution mode. Defaults to account preference (or "approval").
chainIdstringNoUUIDChain to scope this session to
chainyIdstringNoUUIDChainy to scope this session to
bitIdstringNoUUIDBit to scope this session to
agentInstanceIdstringNoUUIDAgent instance to use for this session. It must be an active agent available in the session's workspace (an agent of that workspace or one shared with the whole account); otherwise 400.
primaryContextTypestringNo"chainy" | "chain" | "workspace" | "account"Primary context scope (Chao sessions).
primaryContextIdstringNoUUIDUUID of the primary context entity. Required when primaryContextType is set.
metadataobjectNo—Free-form key/value metadata stored with the session.

Response ​

Response Example ​
json
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "title": "Spanish Learning Coach",
    "status": "active",
    "sessionType": "chat",
    "mode": "approval",
    "startedAt": "2026-03-17T10:00:00.000Z",
    "lastActivityAt": "2026-03-17T10:00:00.000Z",
    "archivedAt": null,
    "pinnedAt": null,
    "metadata": {
      "title": "Spanish Learning Coach"
    }
  }
}

The metadata object in the response surfaces a curated set of keys (title, assistantPreset, selectedModelKey, selectedModelProvider); it is null when none are present.

Code Examples ​

Use the id of one of your Chains as $CHAIN_ID.

bash
curl -X POST https://api.chainabit.com/api/v1/ai/sessions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Spanish Learning Coach",
    "chainId": "'"$CHAIN_ID"'",
    "metadata": {
      "goal": "Improve daily vocabulary retention"
    }
  }'
javascript
const chainId = process.env.CHAIN_ID; // id of the Chain to scope this session to

const res = await fetch(`${BASE_URL}/ai/sessions`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "Spanish Learning Coach",
    chainId,
    metadata: {
      goal: "Improve daily vocabulary retention",
    },
  }),
});
const { data } = await res.json();
python
import os
import requests

chain_id = os.environ["CHAIN_ID"]  # id of the Chain to scope this session to

res = requests.post(
    f"{BASE_URL}/ai/sessions",
    headers={
        "Authorization": f"Bearer {TOKEN}",
        "Content-Type": "application/json",
    },
    json={
        "title": "Spanish Learning Coach",
        "chainId": chain_id,
        "metadata": {
            "goal": "Improve daily vocabulary retention",
        },
    },
)
data = res.json()["data"]
Creating a Chao Session ​

To create a session powered by Chao (Chainabit's behavioral advisor), pass assistantType: "chao" with a Chainy context. Use the id of the Chainy to coach with as $CHAINY_ID.

bash
curl -X POST https://api.chainabit.com/api/v1/ai/sessions \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "My Chainy Coach",
    "assistantType": "chao",
    "primaryContextType": "chainy",
    "primaryContextId": "'"$CHAINY_ID"'"
  }'
javascript
const chainyId = process.env.CHAINY_ID; // id of the Chainy this session is scoped to

const res = await fetch(`${BASE_URL}/ai/sessions`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "My Chainy Coach",
    assistantType: "chao",
    primaryContextType: "chainy",
    primaryContextId: chainyId,
  }),
});
const { data } = await res.json();
python
import os
import requests

chainy_id = os.environ["CHAINY_ID"]  # id of the Chainy this session is scoped to

res = requests.post(
    f"{BASE_URL}/ai/sessions",
    headers={
        "Authorization": f"Bearer {TOKEN}",
        "Content-Type": "application/json",
    },
    json={
        "title": "My Chainy Coach",
        "assistantType": "chao",
        "primaryContextType": "chainy",
        "primaryContextId": chainy_id,
    },
)
data = res.json()["data"]

When assistantType is "chao", the session automatically loads Chainy-scoped memories and productivity context into all AI interactions.

Reasoning and Tool Activity ​

Chao sessions can stream safe activity summaries while a response is being generated. Use payload.activity on events such as tool.started, tool.progress, tool.approval_required, tool.completed, tool.failed, tool.degraded, plan.step_added, and capability.resolved to render status cards.

Raw private Chain-of-Thought is not a public UI contract. If diagnostic cot.* events appear in an internal/debug session, treat them as nonessential metadata and do not show raw reasoning to end users by default.

Persisted message.toolCalls is the stable source for reconstructing tool cards after reload. See AI Messages and SSE Streaming.


GET /ai/sessions/:id ​

Description ​

Get details of a single session.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 60/min

Request ​

  • Path params: id (Session ID)

Response ​

Response Example ​
json
{
  "data": {
    "id": "cm5sess01",
    "title": "Spanish Learning Coach",
    "status": "active",
    "pinnedAt": null,
    "archivedAt": null,
    "messageCount": 5,
    "createdAt": "2026-03-17T10:00:00.000Z",
    "updatedAt": "2026-03-17T11:00:00.000Z"
  }
}

Code Examples ​

Use the id from Create a Session response as $SESSION_ID.

bash
curl https://api.chainabit.com/api/v1/ai/sessions/$SESSION_ID \
  -H "Authorization: Bearer $TOKEN"
javascript
const sessionId = process.env.SESSION_ID; // id from the Create a Session response

const res = await fetch(`${BASE_URL}/ai/sessions/${sessionId}`, {
  headers: { Authorization: `Bearer ${TOKEN}` },
});
const { data } = await res.json();
python
import os
import requests

session_id = os.environ["SESSION_ID"]  # id from the Create a Session response

res = requests.get(
    f"{BASE_URL}/ai/sessions/{session_id}",
    headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]

DELETE /ai/sessions/:id ​

Description ​

End a session. The session is soft-deleted and no longer accepts new messages. Sessions ended this way are permanently deleted after 30 days of inactivity.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 30/min

Request ​

  • Path params: id (Session ID)

Response ​

Response Example ​
json
{
  "data": {
    "id": "cm5sess01",
    "ended": true,
    "endedAt": "2026-03-17T12:00:00.000Z"
  }
}

Code Examples ​

Use the id from Create a Session response as $SESSION_ID.

bash
curl -X DELETE https://api.chainabit.com/api/v1/ai/sessions/$SESSION_ID \
  -H "Authorization: Bearer $TOKEN"
javascript
const sessionId = process.env.SESSION_ID; // id from the Create a Session response

const res = await fetch(`${BASE_URL}/ai/sessions/${sessionId}`, {
  method: "DELETE",
  headers: { Authorization: `Bearer ${TOKEN}` },
});
python
import os
import requests

session_id = os.environ["SESSION_ID"]  # id from the Create a Session response

res = requests.delete(
    f"{BASE_URL}/ai/sessions/{session_id}",
    headers={"Authorization": f"Bearer {TOKEN}"},
)

PATCH /ai/sessions/:id/archive ​

Description ​

Archive an active session. Archived sessions are excluded from the default list but preserved indefinitely. Archived sessions are never auto-deleted.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 30/min

Request ​

  • Path params: id (Session ID)

Response ​

Response Example ​
json
{
  "data": { "count": 1 }
}

Code Examples ​

Use the id from Create a Session response as $SESSION_ID.

bash
curl -X PATCH https://api.chainabit.com/api/v1/ai/sessions/$SESSION_ID/archive \
  -H "Authorization: Bearer $TOKEN"
javascript
const sessionId = process.env.SESSION_ID; // id from the Create a Session response

const res = await fetch(`${BASE_URL}/ai/sessions/${sessionId}/archive`, {
  method: "PATCH",
  headers: { Authorization: `Bearer ${TOKEN}` },
});
python
import os
import requests

session_id = os.environ["SESSION_ID"]  # id from the Create a Session response

res = requests.patch(
    f"{BASE_URL}/ai/sessions/{session_id}/archive",
    headers={"Authorization": f"Bearer {TOKEN}"},
)

PATCH /ai/sessions/:id/unarchive ​

Description ​

Restore an archived session back to active status.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 30/min

Request ​

  • Path params: id (Session ID)

Response ​

Response Example ​
json
{
  "data": { "count": 1 }
}

Code Examples ​

Use the id from Create a Session response as $SESSION_ID.

bash
curl -X PATCH https://api.chainabit.com/api/v1/ai/sessions/$SESSION_ID/unarchive \
  -H "Authorization: Bearer $TOKEN"
javascript
const sessionId = process.env.SESSION_ID; // id from the Create a Session response

const res = await fetch(`${BASE_URL}/ai/sessions/${sessionId}/unarchive`, {
  method: "PATCH",
  headers: { Authorization: `Bearer ${TOKEN}` },
});
python
import os
import requests

session_id = os.environ["SESSION_ID"]  # id from the Create a Session response

res = requests.patch(
    f"{BASE_URL}/ai/sessions/{session_id}/unarchive",
    headers={"Authorization": f"Bearer {TOKEN}"},
)

PATCH /ai/sessions/:id/pin ​

Description ​

Pin a session. Pinning is a client-side organizational marker and does not change the session status. Both active and archived sessions can be pinned.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 60/min

Request ​

  • Path params: id (Session ID)

Response ​

Response Example ​
json
{
  "data": { "count": 1 }
}

Code Examples ​

Use the id from Create a Session response as $SESSION_ID.

bash
curl -X PATCH https://api.chainabit.com/api/v1/ai/sessions/$SESSION_ID/pin \
  -H "Authorization: Bearer $TOKEN"
javascript
const sessionId = process.env.SESSION_ID; // id from the Create a Session response

const res = await fetch(`${BASE_URL}/ai/sessions/${sessionId}/pin`, {
  method: "PATCH",
  headers: { Authorization: `Bearer ${TOKEN}` },
});
python
import os
import requests

session_id = os.environ["SESSION_ID"]  # id from the Create a Session response

res = requests.patch(
    f"{BASE_URL}/ai/sessions/{session_id}/pin",
    headers={"Authorization": f"Bearer {TOKEN}"},
)

PATCH /ai/sessions/:id/unpin ​

Description ​

Unpin a pinned session.

Authentication: JWT Bearer token + active AI entitlement required. Rate limit: 60/min

Request ​

  • Path params: id (Session ID)

Response ​

Response Example ​
json
{
  "data": { "count": 1 }
}

Code Examples ​

Use the id from Create a Session response as $SESSION_ID.

bash
curl -X PATCH https://api.chainabit.com/api/v1/ai/sessions/$SESSION_ID/unpin \
  -H "Authorization: Bearer $TOKEN"
javascript
const sessionId = process.env.SESSION_ID; // id from the Create a Session response

const res = await fetch(`${BASE_URL}/ai/sessions/${sessionId}/unpin`, {
  method: "PATCH",
  headers: { Authorization: `Bearer ${TOKEN}` },
});
python
import os
import requests

session_id = os.environ["SESSION_ID"]  # id from the Create a Session response

res = requests.patch(
    f"{BASE_URL}/ai/sessions/{session_id}/unpin",
    headers={"Authorization": f"Bearer {TOKEN}"},
)

Sharing a Session ​

Only the session owner can create, change or revoke a share link. Invited participants and workspace members can collaborate in a session but cannot publish it (see Conversation Participants & Lenses). Sharing is scoped to Chao sessions accessed through a workspace.

Every share link has one of two audiences:

AudiencenoIndexWho can find it
PublicfalseAnyone with the link can open it, and search engines may index the conversation.
Link onlytrueOnly people who have the link can open it. Search engines are asked not to index it.

A new share is public. The owner can switch a share to link only at any time with PATCH; doing so keeps the same link. Copies that a search engine has already made can remain until it refreshes them.

POST /workspaces/:workspaceId/ai/sessions/:sessionId/share ​

Description ​

Creates a read-only share link for the session. Without a noIndex value the share is public. Calling this again on an already-shared session returns the existing share rather than creating a duplicate — the urlShort does not change, and an existing share keeps its audience unless you send a noIndex value that differs. A share that was revoked is reactivated with the audience you request (public when you send none).

Authentication: JWT Bearer token + active AI entitlement required (session owner only). Rate limit: 20/min

Request ​

  • Path params: workspaceId, sessionId
  • Body (optional):
FieldTypeRequiredDescription
noIndexbooleanNofalse makes the share public, true makes it link only. Omit it to use the default for a new share (public) or to keep the audience of an existing one.

Response ​

Response Example ​
json
{
  "data": {
    "id": "5e3a1c0d-8b7f-4e2a-9c61-0d4f7a2b9e13",
    "shareUrl": "https://chainabit.com/cs/5e3a1c0d-8b7f-4e2a-9c61-0d4f7a2b9e13?share=a3f2b9c1e4",
    "urlShort": "a3f2b9c1e4",
    "noIndex": false,
    "openCount": 0
  }
}
Response Fields ​
FieldTypeDescription
idstringIdentifier of the share link
shareUrlstringFull URL for the share link
urlShortstringShort token used in the URL and in GET /cs/:urlShort
noIndexbooleanfalse for a public share, true for link only
openCountintegerNumber of times the link has been opened

Code Examples ​

Use the id from Create a Session response as $SESSION_ID.

bash
curl -X POST https://api.chainabit.com/api/v1/workspaces/$WORKSPACE_ID/ai/sessions/$SESSION_ID/share \
  -H "Authorization: Bearer $TOKEN"
javascript
const workspaceId = process.env.WORKSPACE_ID;
const sessionId = process.env.SESSION_ID; // id from the Create a Session response

const res = await fetch(
  `${BASE_URL}/workspaces/${workspaceId}/ai/sessions/${sessionId}/share`,
  { method: "POST", headers: { Authorization: `Bearer ${TOKEN}` } }
);
const { data } = await res.json();
console.log(data.shareUrl);
python
import os
import requests

workspace_id = os.environ["WORKSPACE_ID"]
session_id = os.environ["SESSION_ID"]  # id from the Create a Session response

res = requests.post(
    f"{BASE_URL}/workspaces/{workspace_id}/ai/sessions/{session_id}/share",
    headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]
print(data["shareUrl"])

PATCH /workspaces/:workspaceId/ai/sessions/:sessionId/share ​

Description ​

Switches the session's active share between public and link only. The link and its urlShort do not change. Sending the audience the share already has is a no-op. This route never creates or reactivates a share: a session with no active share returns 404.

Authentication: JWT Bearer token + active AI entitlement required (session owner only). Rate limit: 20/min

Request ​

  • Path params: workspaceId, sessionId
  • Body:
FieldTypeRequiredDescription
noIndexbooleanYesfalse for public, true for link only. Any other value returns 400.

Response ​

The response has the same shape as POST. Use the noIndex field to confirm the audience; openCount is not reported by this route and is always 0.

Code Examples ​

bash
curl -X PATCH https://api.chainabit.com/api/v1/workspaces/$WORKSPACE_ID/ai/sessions/$SESSION_ID/share \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"noIndex": true}'
javascript
const workspaceId = process.env.WORKSPACE_ID;
const sessionId = process.env.SESSION_ID; // id from the Create a Session response

const res = await fetch(
  `${BASE_URL}/workspaces/${workspaceId}/ai/sessions/${sessionId}/share`,
  {
    method: "PATCH",
    headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json" },
    body: JSON.stringify({ noIndex: true }),
  }
);
const { data } = await res.json();
console.log(data.noIndex); // true: link only
python
import os
import requests

workspace_id = os.environ["WORKSPACE_ID"]
session_id = os.environ["SESSION_ID"]  # id from the Create a Session response

res = requests.patch(
    f"{BASE_URL}/workspaces/{workspace_id}/ai/sessions/{session_id}/share",
    headers={"Authorization": f"Bearer {TOKEN}"},
    json={"noIndex": True},
)
print(res.json()["data"]["noIndex"])  # True: link only

DELETE /workspaces/:workspaceId/ai/sessions/:sessionId/share ​

Description ​

Revokes the session's active share link. The previous urlShort stops resolving immediately.

Authentication: JWT Bearer token + active AI entitlement required (session owner only). Rate limit: 20/min

Request ​

  • Path params: workspaceId, sessionId

Response ​

Response Example ​
json
{
  "data": { "revoked": true }
}

Code Examples ​

bash
curl -X DELETE https://api.chainabit.com/api/v1/workspaces/$WORKSPACE_ID/ai/sessions/$SESSION_ID/share \
  -H "Authorization: Bearer $TOKEN"
javascript
const workspaceId = process.env.WORKSPACE_ID;
const sessionId = process.env.SESSION_ID; // id from the Create a Session response

const res = await fetch(
  `${BASE_URL}/workspaces/${workspaceId}/ai/sessions/${sessionId}/share`,
  { method: "DELETE", headers: { Authorization: `Bearer ${TOKEN}` } }
);
const { data } = await res.json();
python
import os
import requests

workspace_id = os.environ["WORKSPACE_ID"]
session_id = os.environ["SESSION_ID"]  # id from the Create a Session response

res = requests.delete(
    f"{BASE_URL}/workspaces/{workspace_id}/ai/sessions/{session_id}/share",
    headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]

GET /cs/:urlShort ​

Description ​

Resolve a shared session by its short token. This endpoint is public and unauthenticated. Revoked, expired, and malformed tokens all resolve to a generic 404 Not Found — the response never distinguishes between those cases.

Authentication: None (public). Rate limit: 60 requests per 60 seconds.

Request ​

Response ​

Response Example ​
json
{
  "data": {
    "title": "Spanish Learning Coach",
    "messages": [
      {
        "id": "msg_01",
        "role": "user",
        "content": "How am I doing with my Morning Run chain?",
        "createdAt": "2026-03-17T10:00:00.000Z"
      }
    ]
  }
}
Response Fields ​
FieldTypeDescription
titlestring | nullSession title
messagesarraySession messages, each with id, role, content, createdAt

Code Examples ​

bash
curl https://api.chainabit.com/api/v1/cs/a3f2b9c1e4
javascript
const urlShort = "a3f2b9c1e4"; // from a share response's data.urlShort

const res = await fetch(`${BASE_URL}/cs/${urlShort}`);
const { data } = await res.json();
python
import requests

url_short = "a3f2b9c1e4"  # from a share response's data.urlShort

res = requests.get(f"{BASE_URL}/cs/{url_short}")
data = res.json()["data"]

Data Retention ​

Sessions ended via DELETE /ai/sessions/:id are soft-deleted and permanently removed after 30 days of inactivity. All messages within the session are deleted at the same time.

To preserve a session indefinitely, archive it with PATCH /ai/sessions/:id/archive before deleting — archived sessions are never auto-deleted.

Built with purpose.