Activity
Retrieve the activity feed for any CRM record, including interactions, tasks, and notes — as independently paginated sections or one merged timeline.
The activity endpoint returns a unified feed of everything that happened on a record. It aggregates interactions (emails, meetings), tasks, and notes into a single response. You can request the data as independently paginated sections (the default) or as one merged chronological timeline.
Get Activity Feed
GET /api/v1/activity/{object}/{id}Returns the activity feed for a specific record.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
object | string | The object name (e.g. contacts, companies) |
id | UUID | The record ID |
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
view | string | sections | Response shape. sections returns three independently paginated sections. timeline merges all items into one chronological feed. |
include | string | interactions,tasks,notes | Comma-separated list of sections to include. Accepted values: interactions, tasks, notes. |
channel | string | -- | Filter interactions by channel (e.g. email, meeting, linkedin, whatsapp). Only affects the interactions section. |
cursor | string | -- | Pagination cursor for the interactions section, taken from a previous response's next_cursor. |
limit | integer | 20 | Number of items per section, or total items in the merged timeline (max 50). |
Interactions are only tracked on contacts and companies. On any other object, the interactions section is returned with available: false and a reason, never a silently empty list.
Example Request
curl -X GET "https://kasar.app/api/v1/activity/contacts/550e8400-e29b-41d4-a716-446655440000?include=interactions,tasks,notes&channel=email&limit=10" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..."Response (sections view)
The top level always includes a record reference. Each included section is an object with items, total, has_more, and (when more items remain) next_cursor:
{
"record": {
"object_name": "contacts",
"id": "550e8400-e29b-41d4-a716-446655440000",
"display": "Alice Martin"
},
"interactions": {
"available": true,
"items": [
{
"id": "a1b2c3d4-...",
"channel": "email",
"date": "2025-03-10T14:22:00Z",
"direction": "inbound",
"subject": "Follow-up on proposal",
"preview": "Hi Alice, I wanted to circle back on the proposal we discussed…",
"participants": null
}
],
"total": 34,
"has_more": true,
"next_cursor": "eyJvZmZzZXQiOjEwLCJsaW1pdCI6MTB9"
},
"tasks": {
"items": [
{
"id": "e5f6a7b8-...",
"title": "Send updated contract",
"status": "open",
"due_date": "2025-03-15",
"priority": "urgent",
"assignee": { "id": "b2c3d4e5-...", "display": "Bob Dupont" },
"date": "2025-03-15"
}
],
"total": 5,
"has_more": false
},
"notes": {
"items": [
{
"id": "c3d4e5f6-...",
"title": "Call recap",
"preview": "Alice confirmed budget approval for Q2…",
"author": { "id": "b2c3d4e5-...", "display": "Bob Dupont" },
"date": "2025-03-09T11:05:00Z"
}
],
"total": 2,
"has_more": false
}
}Sections that are not listed in the include parameter are omitted from the response entirely.
Section item shapes
Each section normalizes its rows into a compact shape:
- interactions —
id,channel,date,direction,subject,preview(plain-text snippet, max 200 chars),participants,thread_id(the conversation the message belongs to). - tasks —
id,title,status(openordone),due_date,priority,assignee({ id, display }ornull),date. - notes —
id,title,preview,author({ id, display }ornull),date.
When the interactions section is unavailable (object is not contacts or companies), it is returned as:
{
"interactions": {
"available": false,
"reason": "Interactions are only tracked on contacts and companies.",
"items": [],
"total": 0,
"has_more": false
}
}Response (timeline view)
With view=timeline, the three sources are merged into one chronologically descending timeline (capped at limit). Each entry carries a kind (interaction, task, or note) plus that type's normalized fields. Per-section totals are summarized in counts:
curl -X GET "https://kasar.app/api/v1/activity/contacts/550e8400-...?view=timeline&limit=20" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..."{
"record": {
"object_name": "contacts",
"id": "550e8400-e29b-41d4-a716-446655440000",
"display": "Alice Martin"
},
"interactions_available": true,
"counts": {
"interactions": 34,
"tasks": 5,
"notes": 2
},
"timeline": [
{
"kind": "task",
"id": "e5f6a7b8-...",
"title": "Send updated contract",
"status": "open",
"due_date": "2025-03-15",
"priority": "urgent",
"assignee": { "id": "b2c3d4e5-...", "display": "Bob Dupont" },
"date": "2025-03-15"
},
{
"kind": "interaction",
"id": "a1b2c3d4-...",
"channel": "email",
"date": "2025-03-10T14:22:00Z",
"direction": "inbound",
"subject": "Follow-up on proposal",
"preview": "Hi Alice, I wanted to circle back on the proposal we discussed…",
"participants": null
}
],
"has_more": true
}In timeline view, interactions_available reflects whether the interactions source was usable for this object (omitted when interactions is not included). has_more is true if any underlying section still has more items.
Filtering by Channel
Use the channel parameter to narrow down interactions. This only affects the interactions section; tasks and notes are returned unfiltered.
curl -X GET "https://kasar.app/api/v1/activity/companies/99aabb00-...?include=interactions&channel=meeting" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..."Pagination
In sections view, each section reports has_more and, when there are more items, a next_cursor. The interactions section's cursor can be passed back as the cursor query parameter to fetch the next page of interactions:
curl -X GET "https://kasar.app/api/v1/activity/contacts/550e8400-...?cursor=eyJvZmZzZXQiOjEwLCJsaW1pdCI6MTB9" \
-H "Authorization: Bearer ksr_a1b2c3d4e5f6..."When a section's has_more is false, you have reached its last page (and no next_cursor is present).
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | MISSING_REQUIRED_FIELD | The object name or record ID was not provided |
| 400 | INVALID_OBJECT | The object name does not exist (response includes available_values) |
| 400 | RECORD_NOT_FOUND | No visible record found with the given ID |
| 401 | UNAUTHORIZED | Invalid or missing API token |