Issues
Session API for issue list, status, merge, snooze, and bulk actions.
All routes below are under /api/v1 and require a dashboard session. Org scope comes from the session; PostgreSQL RLS enforces isolation.
Calling the Issues API
Login returns 204 plus a cookie, then GET /api/v1/issues. Unauthenticated calls return 401 { "error": "unauthenticated" }.
Ingest is separate: Ingest. Occurrences: Events.
First call with the seed user
Login returns 204 and Set-Cookie (Epure.sid on local HTTP).
curl -sS -c cookies.txt -D - -o /dev/null -X POST \
"http://localhost:8080/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"email":"dev@epure.local","password":"devpassword"}'HTTP/1.1 204 No Content
Set-Cookie: Epure.sid=...; HttpOnly; Path=/; SameSite=Laxcurl -sS -b cookies.txt \
"http://localhost:8080/api/v1/issues?q=is:unresolved&window=7d"DSN headers on this path → 401. Use the cookie.
How do I list issues?
GET /api/v1/issues?project_id={uuid}&q={query}&window={window}&sort={sort}| Query | Default | Values |
|---|---|---|
project_id | all org projects | UUID |
q | empty | Linear-style tokens + free text |
window | 7d | 24h, 7d, 14d, 30d, 90d |
sort | last_seen_desc | last_seen_asc, events_desc, events_asc, first_seen_desc, first_seen_asc, title_asc |
Query tokens (q)
| Token | Effect |
|---|---|
is:unresolved / is:open | status unresolved |
is:resolved | status resolved |
is:ignored | status ignored |
is:regression | status regression |
is:snoozed | active snooze hold |
env:{name} | environment |
release:{version} | release |
user.email:{pattern} | user email pattern |
level:{level} | level |
| other tokens | free-text substring |
Response 200
{
"issues": [
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"org_id": "11111111-1111-4111-8111-111111111111",
"project_id": "550e8400-e29b-41d4-a716-446655440000",
"fingerprint": "a3f1…",
"title": "TypeError: Cannot read property 'x'",
"status": "unresolved",
"level": "error",
"environment": "local",
"release": "my-app@0.0.0",
"event_count": 42,
"unique_user_count": 3,
"last_seen_at": "2026-09-17T12:00:00Z",
"first_seen_at": "2026-09-16T08:00:00Z",
"resolved_in_release": null,
"snoozed": false,
"snooze_until": null,
"snooze_until_count": null,
"snooze_until_users": null
}
]
}Merged children are omitted from the default list (merge_parent_id IS NULL).
How do I fetch issue trends?
POST /api/v1/issues/trends
Content-Type: application/json{ "issue_ids": ["7c9e6679-7425-40de-944b-e07fc1f90ae7"] }Max 200 IDs. Empty list → { "trends": [] }. Over 200 → 400.
Response: { "trends": [ { "issue_id": "…", "buckets": [ { "start": "…", "count": 3 } ] } ] }.
How do I patch an issue?
PATCH /api/v1/issues/{id}{ "status": "resolved", "resolved_in_release": "1.4.0" }| Field | Notes |
|---|---|
status | unresolved | resolved | ignored | regression |
resolved_in_release | optional string for “resolved in next release” |
At least one field required. Invalid status → 400. Missing issue → 404. Success returns the updated IssueSummary object.
curl -sS -b cookies.txt -X PATCH \
"http://localhost:8080/api/v1/issues/${ISSUE_ID}" \
-H "Content-Type: application/json" \
-d '{"status":"resolved"}'How do I snooze an issue?
POST /api/v1/issues/{id}/snooze{ "mode": "hours" }mode | Meaning |
|---|---|
hours or 4h | snooze 4 hours |
occurrences or 100 | until 100 occurrences |
users or 10 | until 10 unique users |
Unknown mode → 400. Success → updated issue JSON.
Bulk update or delete
PATCH /api/v1/issues/bulk{ "ids": ["7c9e6679-7425-40de-944b-e07fc1f90ae7"], "action": "resolve" }action | Resulting status |
|---|---|
resolve | resolved |
ignore | ignored |
reopen | unresolved |
| or a valid status string | that status |
Response: { "updated": 1 }.
Merge or split issues
POST /api/v1/issues/merge{
"canonical_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"merge_ids": ["aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"]
}POST /api/v1/issues/split{
"canonical_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"split_ids": ["aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"]
}Empty merge_ids / split_ids → 400. Response: { "updated": <count> }.
GET /api/v1/issues/{id}/mergedLists child issues merged into {id}, in the same { "issues": […] } shape as the list route.
Where are events for an issue?
Occurrence routes live on Events: GET /api/v1/issues/{id}/events, timeline, releases, and crash-dialog feedback. Those paths need a session cookie; a DSN cannot list occurrences. Spike-valve floods can leave fewer stored rows than event_count.
Can I list issues with the DSN?
No. The DSN is ingest only. Login first (POST /api/v1/auth/login → 204 plus cookie), then GET /api/v1/issues. DSN headers here return 401 { "error": "unauthenticated" }. Org scope comes from the session and RLS: Authentication.