Get activity feed for a process
The activity feed gives you a full audit trail of everything that’s happened on a process — task completions, comments, status changes, assignments, and system events. It’s useful for compliance, auditing, and building custom dashboards.
GET /organizations/{org}/activity-feeds
This endpoint returns activities across the entire organization. To scope it to a single process, pass entity_type=run and entity_id={process_id} as query parameters.
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer {access_token} |
Accept | Yes | application/json |
X-Tallyfy-Client | Yes | APIClient |
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_type | string | No* | Entity type to filter: checklist, run, step, task, thread |
entity_id | string | No* | ID of the specific entity |
type | string | No | Activity category: Comment, Task, Step, Process, Blueprint, User, Organization, Tag, Group |
verb | string | No | Action filter (see verb values below) |
actor_type | string | No | user or guest |
actor_id | integer | No | Specific user or guest ID |
actor_email | string | No | Actor’s email — resolves to actor_id and actor_type automatically |
source | string | No | Member, Guest, or Webhook |
created_after | string | No | Start date filter (YYYY-MM-DD format, inclusive) |
created_before | string | No | End date filter (YYYY-MM-DD format, inclusive) |
search | string | No | Search activity descriptions (2-100 characters) |
field | string | No | Filter by changed field name (e.g. title, status) |
origin_type | string | No | Filter auto-launched activities by origin: checklist, run, step, task |
origin_id | string | No | Specific origin entity ID (requires origin_type) |
page | integer | No | Page number (default: 1) |
per_page | integer | No | Results per page (default: 20) |
sort | string | No | Sort order, e.g. -created_at for newest first |
*Use entity_type=run with entity_id to scope results to a single process.
The full set of supported verbs:
created · updated · owners-updated · uploaded · completed · uncompleted · deleted · re-ordered · commented · issue-reported · issue-resolved · archived · unarchived · re-opened · emitted · enabled · disabled · comment-deleted · invited · invite-accepted · linked · unlinked
const orgId = 'your_org_id';const processId = 'your_process_id';const token = 'your_access_token';
const params = new URLSearchParams({ entity_type: 'run', entity_id: processId, per_page: '50', sort: '-created_at'});
const response = await fetch( `https://go.tallyfy.com/api/organizations/${orgId}/activity-feeds?${params}`, { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Accept': 'application/json', 'X-Tallyfy-Client': 'APIClient' } });
const data = await response.json();console.log(`Total activities: ${data.meta.pagination.total}`);data.data.forEach(a => { console.log(`${a.created_at} - ${a.verb} - ${a.description}`);});import requests
BASE_URL = "https://go.tallyfy.com/api"org_id = "your_org_id"token = "your_access_token"
headers = { "Authorization": f"Bearer {token}", "Accept": "application/json", "X-Tallyfy-Client": "APIClient"}
def get_process_activities(process_id, verb=None, activity_type=None, page=1, per_page=50): """Fetch activity feed for a specific process.""" params = { "entity_type": "run", "entity_id": process_id, "page": page, "per_page": per_page, "sort": "-created_at" } if verb: params["verb"] = verb if activity_type: params["type"] = activity_type
resp = requests.get( f"{BASE_URL}/organizations/{org_id}/activity-feeds", headers=headers, params=params ) resp.raise_for_status() return resp.json()
# Get all activities for a processresult = get_process_activities("process_id_123")for activity in result["data"]: print(f"{activity['created_at']} - {activity['verb']} - {activity['description']}")
# Get only task completionscompletions = get_process_activities( "process_id_123", verb="completed", activity_type="Task")import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;
public class TallyfyActivityFeed { private static final String BASE_URL = "https://go.tallyfy.com/api"; private final String orgId; private final String token; private final HttpClient client = HttpClient.newHttpClient();
public TallyfyActivityFeed(String orgId, String token) { this.orgId = orgId; this.token = token; }
public String getProcessActivities(String processId, String verb, String type, int page, int perPage) throws Exception { StringBuilder qs = new StringBuilder("?entity_type=run"); qs.append("&entity_id=").append(processId); qs.append("&page=").append(page); qs.append("&per_page=").append(perPage); qs.append("&sort=-created_at"); if (verb != null) qs.append("&verb=").append(verb); if (type != null) qs.append("&type=").append(type);
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(BASE_URL + "/organizations/" + orgId + "/activity-feeds" + qs)) .header("Authorization", "Bearer " + token) .header("Accept", "application/json") .header("X-Tallyfy-Client", "APIClient") .GET() .build();
HttpResponse<String> resp = client.send( request, HttpResponse.BodyHandlers.ofString());
if (resp.statusCode() != 200) { throw new RuntimeException("HTTP " + resp.statusCode()); } return resp.body(); }
public static void main(String[] args) throws Exception { var api = new TallyfyActivityFeed("your_org_id", "your_access_token"); String json = api.getProcessActivities( "process_id_123", null, null, 1, 50); System.out.println(json); }}package main
import ( "encoding/json" "fmt" "io" "net/http" "net/url")
const baseURL = "https://go.tallyfy.com/api"
func getProcessActivities(orgID, token, processID string, filters map[string]string) (map[string]interface{}, error) {
u, _ := url.Parse(fmt.Sprintf( "%s/organizations/%s/activity-feeds", baseURL, orgID))
q := u.Query() q.Set("entity_type", "run") q.Set("entity_id", processID) q.Set("sort", "-created_at") for k, v := range filters { if v != "" { q.Set(k, v) } } u.RawQuery = q.Encode()
req, _ := http.NewRequest("GET", u.String(), nil) req.Header.Set("Authorization", "Bearer "+token) req.Header.Set("Accept", "application/json") req.Header.Set("X-Tallyfy-Client", "APIClient")
resp, err := (&http.Client{}).Do(req) if err != nil { return nil, err } defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return nil, fmt.Errorf("API error %d: %s", resp.StatusCode, body) }
var result map[string]interface{} json.NewDecoder(resp.Body).Decode(&result) return result, nil}
func main() { result, err := getProcessActivities( "your_org_id", "your_access_token", "process_id_123", map[string]string{"per_page": "50"}, ) if err != nil { panic(err) } fmt.Println(result)}The response uses Fractal pagination wrapping. Activities sit in data and pagination metadata lives under meta.pagination.
{ "data": [ { "id": 12345, "organization_id": "org_xyz", "verb": ["completed"], "source": ["Member"], "actor_type": ["App\\Models\\User"], "actor_id": [67890], "auditable_type": "App\\Models\\Task", "auditable_id": "task_456", "parentable_type": "App\\Models\\Run", "parentable_id": "run_789", "type": ["Task"], "description": ["Completed task: Review document"], "field": null, "old_value": null, "created_at": "2025-03-15T10:30:00Z", "text": null, "references": null, "actor": [ { "email": "john@example.com", "username": "johnsmith", "first_name": "John", "last_name": "Smith", "full_name": "John Smith", "profile_pic": null, "resize_profile_pic": null } ], "undoable": false, "audit": { "data": { } }, "parent": { "data": { } }, "origin": null } ], "meta": { "pagination": { "total": 145, "count": 20, "per_page": 20, "current_page": 1, "total_pages": 8, "links": { "next": "https://go.tallyfy.com/api/organizations/org_xyz/activity-feeds?page=2" } } }}| Field | Description |
|---|---|
id | Activity feed ID |
organization_id | Organization the activity belongs to |
verb | Array of actions performed (e.g. ["completed"]) |
source | Array indicating who triggered it: Member, Guest, or Webhook |
actor_type | Array of actor model types |
actor_id | Array of actor IDs |
actor | Array of actor detail objects with email, first_name, last_name, full_name, profile_pic |
auditable_type | Model class of the entity acted upon |
auditable_id | ID of the entity acted upon |
parentable_type | Model class of the parent entity |
parentable_id | ID of the parent entity |
type | Array of activity categories (e.g. ["Task"]) |
description | Array of human-readable descriptions |
field | For updates, which field changed (array or null) |
old_value | For updates, the previous value (array or null) |
created_at | When the activity occurred |
text | Extra content such as comment text (array or null) |
references | Related references (array or null) |
undoable | Whether this activity can be undone |
audit | Fractal include — current state of the audited object |
parent | Fractal include — parent object details |
origin | Fractal include — origin entity for auto-launched activities |
audit_state | Snapshot of the audited object’s state (when available) |
parent_state | Snapshot of the parent object’s state (when available) |
The activity_feed_access middleware controls access. You can view the activity feed if you’re:
- An organization admin
- A support user with appropriate access
- The creator of the process (when filtering by
entity_type=run) - A user with PROCESS_READ permission on that process
- Assigned to at least one task in that process
Without a specific entity_type=run filter, admins and support users see all org-level activities. Non-admin users see activities scoped to entities they have permission to access.
The API allows 600 requests per minute. Use pagination and caching to stay within limits when polling for updates.
Code Samples > Managing processes (Runs)
Was this helpful?
- 2025 Tallyfy, Inc.
- Privacy Policy
- Terms of Use
- Report Issue
- Trademarks