Activity API¶
Access commit, pull request, and issue activity across all monitored repositories.
List Activity¶
Get recent activity across all repositories.
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
days |
integer | 7 | Number of days to look back |
organization_id |
UUID | - | Filter by organization |
repository_id |
UUID | - | Filter by repository |
type |
string | - | Activity type: commit, pr, issue |
limit |
integer | 100 | Max results |
offset |
integer | 0 | Pagination offset |
Response¶
{
"items": [
{
"type": "commit",
"repository": "my-org/awesome-project",
"title": "Fix critical bug in authentication",
"author": "jane@example.com",
"timestamp": "2026-02-28T10:30:00Z",
"url": "https://github.com/my-org/awesome-project/commit/abc123"
},
{
"type": "pr",
"repository": "my-org/awesome-project",
"title": "Add OAuth2 support",
"author": "johndoe",
"timestamp": "2026-02-28T09:00:00Z",
"url": "https://github.com/my-org/awesome-project/pull/42"
}
],
"total": 250,
"limit": 100,
"offset": 0
}
List Commits¶
Get commit activity.
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
days |
integer | 7 | Number of days to look back |
organization_id |
UUID | - | Filter by organization |
repository_id |
UUID | - | Filter by repository |
author_email |
string | - | Filter by author email |
limit |
integer | 100 | Max results |
offset |
integer | 0 | Pagination offset |
Response¶
{
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440010",
"sha": "abc123def456",
"message": "Fix critical bug in authentication\n\nThis commit addresses issue #42 by...",
"author_name": "Jane Doe",
"author_email": "jane@example.com",
"authored_at": "2026-01-14T09:12:00Z",
"committed_at": "2026-02-28T10:30:00Z",
"repository": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "awesome-project",
"full_name": "my-org/awesome-project"
},
"stats": {
"additions": 50,
"deletions": 20,
"files_changed": 3
}
}
],
"total": 150,
"limit": 100,
"offset": 0
}
Two timestamps¶
A commit carries both, and they answer different questions:
authored_at: when the work was written. It belongs to the author, and a rebase or squash does not change it. Use it for attribution.committed_at: when it landed. Use it for anything time-windowed.
They differ whenever history is rewritten, which is most of the time on a project that rebases or squash-merges: the example above is work written in January and merged at the end of February.
since and until filter on committed_at, and results are ordered by
it, because that is also what the forges' own filters apply to. Bucketing
by author date puts merged work into windows that already closed.
List Pull Requests¶
Get pull request activity.
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
days |
integer | 30 | Number of days to look back |
organization_id |
UUID | - | Filter by organization |
repository_id |
UUID | - | Filter by repository |
state |
string | - | Filter by state: open, closed, merged |
author |
string | - | Filter by author username |
limit |
integer | 100 | Max results |
offset |
integer | 0 | Pagination offset |
Response¶
{
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440020",
"number": 42,
"title": "Add OAuth2 support",
"body": "This PR adds OAuth2 authentication...",
"state": "open",
"author": "johndoe",
"created_at": "2026-02-28T09:00:00Z",
"updated_at": "2026-02-28T10:00:00Z",
"merged_at": null,
"repository": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "awesome-project",
"full_name": "my-org/awesome-project"
},
"stats": {
"commits": 5,
"additions": 200,
"deletions": 50,
"changed_files": 8
}
}
],
"total": 25,
"limit": 100,
"offset": 0
}
List Issues¶
Get issue activity.
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
days |
integer | 30 | Number of days to look back |
organization_id |
UUID | - | Filter by organization |
repository_id |
UUID | - | Filter by repository |
state |
string | - | Filter by state: open, closed |
author |
string | - | Filter by author username |
limit |
integer | 100 | Max results |
offset |
integer | 0 | Pagination offset |
Response¶
{
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440030",
"number": 100,
"title": "Bug: Login fails on mobile",
"body": "When trying to login on mobile devices...",
"state": "open",
"author": "reporter",
"labels": ["bug", "high-priority"],
"created_at": "2026-02-26T10:00:00Z",
"updated_at": "2026-02-28T08:00:00Z",
"closed_at": null,
"repository": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "awesome-project",
"full_name": "my-org/awesome-project"
}
}
],
"total": 10,
"limit": 100,
"offset": 0
}
Activity Summary¶
Get aggregated activity statistics.
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
days |
integer | 30 | Period to analyze |
organization_id |
UUID | - | Filter by organization |
Response¶
{
"period": {
"start": "2026-01-29T00:00:00Z",
"end": "2026-02-28T23:59:59Z",
"days": 30
},
"commits": {
"total": 500,
"by_day": [
{"date": "2026-02-28", "count": 25},
{"date": "2026-02-27", "count": 30}
]
},
"pull_requests": {
"opened": 50,
"merged": 45,
"closed": 5,
"avg_merge_time_hours": 24
},
"issues": {
"opened": 30,
"closed": 25,
"avg_close_time_hours": 48
},
"contributors": {
"total": 25,
"active": 18,
"new": 3
}
}
Example: Weekly Activity Report¶
import httpx
from datetime import datetime
client = httpx.Client(
base_url="http://localhost:8000/api",
headers={"Authorization": f"Bearer {token}"}
)
# Get activity summary for the past week
summary = client.get("/activity/summary", params={"days": 7}).json()
print(f"Weekly Activity Report ({summary['period']['start'][:10]} to {summary['period']['end'][:10]})")
print(f"=" * 60)
print(f"Commits: {summary['commits']['total']}")
print(f"Pull Requests: {summary['pull_requests']['opened']} opened, {summary['pull_requests']['merged']} merged")
print(f"Issues: {summary['issues']['opened']} opened, {summary['issues']['closed']} closed")
print(f"Active Contributors: {summary['contributors']['active']}")
# Get top contributors
commits = client.get("/activity/commits", params={"days": 7, "limit": 500}).json()
# Count commits per author
from collections import Counter
author_commits = Counter(c["author_email"] for c in commits["items"])
print(f"\nTop Contributors:")
for author, count in author_commits.most_common(5):
print(f" {author}: {count} commits")