List membership log
Paginate a list's membership history.
Returns every time a company or a person entered or left the list, had its owner changed, or had its monitoring switched on or off, newest first. Only real changes are recorded: re-adding a member that is already there writes nothing.
Route
GET/api/v3/lists/{kind}/{list_id}/membership-logs
Access modes
Use a workspace API key. The workspace is inferred from the key.
Authorization: Bearer sk_live_...Path parameters
| Parameter | Type | Description |
|---|---|---|
| kind | string | company or profile. It matches the kind of the list. |
| list_id | integer | ID of the list. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number, starting at 1. Defaults to 1. |
| page_size | integer | Items per page. Defaults to 25, maximum 100. |
Example request
curl "https://api.getsillage.com/api/v3/lists/company/12/membership-logs?page=1&page_size=25" \
-H "Authorization: Bearer $SILLAGE_API_KEY"Success response
Status: 200 OK
{
"data": [
{
"id": 5103,
"transition": "entered",
"reason": "api",
"reason_detail": null,
"previous_value": null,
"new_value": null,
"created_at": "2026-10-02T09:15:00.000Z",
"company": {
"id": 301,
"name": "Acme",
"domain": "acme.com",
"linkedin_url": "https://www.linkedin.com/company/acme",
"linkedin_handle": "acme",
"logo_url": "https://media.licdn.com/dms/image/acme-logo.png"
}
}
],
"meta": {
"pagination": {
"page": 1,
"page_size": 25,
"page_count": 1,
"total": 1
}
}
}Response fields
| Field | Type | Description |
|---|---|---|
| data[].id | integer | ID of the history entry. |
| data[].transition | string | What changed: entered (joined the list), left (left the list), owner_changed (its owner changed) or bucket_changed (monitoring was switched on or off for it). |
| data[].reason | string | Why it happened: manual, csv_import, api, rule_match or rule_unmatch (a smart list added or removed it), or mode_switch. |
| data[].reason_detail | object or null | More context when there is some, for example { "user_email": "..." } with the email of the person who acted. Its keys are snake_case. null otherwise. |
| data[].previous_value | string or null | The value before the change, on entries that record one. On a bucket_changed entry it is essential, or null when the account was not monitored. null otherwise. |
| data[].new_value | string or null | The value after the change, on entries that record one. On a bucket_changed entry it is essential, or null when the account was not monitored. null otherwise. |
| data[].created_at | string | When it happened, as an ISO 8601 timestamp. |
| data[].company | object or null | On a company list: the company the entry is about, as a summary: id (its ID in your workspace), name, domain, linkedin_url, linkedin_handle and logo_url. null when the company is no longer in the workspace. Left out on a list of people. |
| data[].lead | object or null | On a list of people: the person the entry is about, as a summary: id (the ID of the lead), full_name, first_name, last_name, linkedin_url, linkedin_headline, position and avatar_url. null when the person is no longer in the workspace. Left out on a list of companies. |
| meta.pagination | object | Pagination metadata: page, page_size, page_count and total. See Pagination. |
Errors
| Status | Meaning |
|---|---|
| 401 | The API key is missing or invalid. |
| 404 | The list does not exist. |
| 422 | kind, list_id or a query parameter is not valid. |
| 429 | Rate limit exceeded. |
| 500 | An unexpected server error occurred. |
Error responses use RFC 9457 problem documents with Content-Type: application/problem+json. type is always about:blank; code tells one problem from another, detail says what went wrong this time, and errors names the field at fault.