Owlmetry
API Reference

Issues

Issue tracking API — list, view, update, merge issues and manage comments.

Manage issues — errors automatically detected and grouped from ingested events.

GET /v1/projects/:projectId/issues

List issues for a project. Results are ordered by most recently seen.

Auth required: Yes (issues:read permission or JWT)

Query parameters

ParameterTypeDescription
statusstringFilter by status: new, in_progress, resolved, silenced, regressed, snoozed.
app_idstringFilter to a specific app.
is_devstringFilter by dev mode: true or false. Takes precedence over data_mode.
data_modestringproduction, development, or all (default when omitted).
cursorstringCursor from previous response for pagination.
limitnumberItems per page (1-200, default 50).

Response

{
  "issues": [
    {
      "id": "uuid",
      "app_id": "uuid",
      "project_id": "uuid",
      "status": "new",
      "title": "Connection refused",
      "source_module": "NetworkService",
      "is_dev": false,
      "occurrence_count": 42,
      "unique_user_count": 15,
      "resolved_at_version": null,
      "first_seen_sdk_version": "0.1.0",
      "last_seen_sdk_version": "0.1.2",
      "first_seen_at": "2024-01-15T10:00:00.000Z",
      "last_seen_at": "2024-01-15T14:30:00.000Z",
      "last_notified_at": "2024-01-15T13:00:00.000Z",
      "snoozed_at": null,
      "created_at": "2024-01-15T10:00:00.000Z",
      "updated_at": "2024-01-15T14:30:00.000Z",
      "fingerprints": ["a1b2c3..."],
      "app_name": "iOS App"
    }
  ],
  "cursor": "uuid-or-null",
  "has_more": false
}

GET /v1/projects/:projectId/issues/:issueId

Get full issue details including paginated occurrences, comments, and fingerprints.

Auth required: Yes (issues:read)

Query parameters

ParameterTypeDescription
occurrence_cursorstringCursor for occurrence pagination.
occurrence_limitnumberMax occurrences per page (1-200, default 50).

Response

Extends the list response with:

{
  "occurrences": [
    {
      "id": "uuid",
      "issue_id": "uuid",
      "session_id": "uuid",
      "user_id": "user123",
      "app_version": "2.1.0",
      "sdk_name": "owlmetry-swift",
      "sdk_version": "0.1.2",
      "environment": "ios",
      "event_id": "uuid",
      "country_code": "US",
      "timestamp": "2024-01-15T14:30:00.000Z",
      "created_at": "2024-01-15T14:30:01.000Z"
    }
  ],
  "occurrence_cursor": "uuid-or-null",
  "occurrence_has_more": false,
  "comments": [
    {
      "id": "uuid",
      "issue_id": "uuid",
      "author_type": "user",
      "author_id": "uuid",
      "author_name": "Jane Doe",
      "body": "Investigating root cause...",
      "created_at": "2024-01-15T15:00:00.000Z",
      "updated_at": "2024-01-15T15:00:00.000Z"
    }
  ],
  "attachments": [
    {
      "id": "uuid",
      "event_id": "uuid",
      "original_filename": "crash.log",
      "content_type": "text/plain",
      "size_bytes": 2048,
      "uploaded_at": "2024-01-15T14:30:02.000Z",
      "created_at": "2024-01-15T14:30:01.000Z"
    }
  ]
}

The attachments array contains up to 100 non-deleted attachments associated with the issue (most recent first). For pagination across all attachments linked to an issue, use the /v1/attachments?issue_id=:issueId endpoint.

PATCH /v1/projects/:projectId/issues/:issueId

Update issue status. Validates status transitions.

Auth required: Yes (issues:write)

Request body

FieldTypeRequiredDescription
statusstringYesTarget status: new, in_progress, resolved, silenced, snoozed. Note: regressed is set automatically by the scan job, and snoozed → new is also a job-driven transition (the scan flips a snoozed issue back to new on its next occurrence).
resolved_at_versionstringWhen status is resolvedApp version where the fix was applied. Required when resolving — powers regression detection. If you don't have a fix version, use silenced (known issue you don't want to hear about again) or snoozed (suspected one-off — auto-reopens on next occurrence). Cleared automatically when transitioning back to new or in_progress.

Valid status transitions

FromAllowed targets
newin_progress, resolved, silenced, snoozed
in_progressnew, resolved, silenced, snoozed
resolvednew, silenced, snoozed
regressedin_progress, resolved, silenced, snoozed
silencednew, in_progress, resolved, snoozed
snoozednew, in_progress, resolved, silenced

Returns 400 if the transition is not allowed, or if status=resolved is sent without a non-empty resolved_at_version.

snoozed_at is set to the server clock when the issue transitions into snoozed, and cleared on any transition out (including the automatic snoozed → new transition fired by the issue-scan job on the next occurrence). The auto-revert also re-fires the same issue.new push that brand-new prod issues trigger.

POST /v1/projects/:projectId/issues/:issueId/merge

Merge a source issue into the target issue. Moves all fingerprints, occurrences (deduplicated by session), and comments to the target. Deletes the source.

Auth required: Yes (issues:write)

Request body

FieldTypeRequiredDescription
source_issue_idstringYesThe issue to merge from (will be deleted).

Both issues must belong to the same project. Returns 400 if merging into itself.

GET /v1/projects/:projectId/issues/:issueId/comments

List comments on an issue in chronological order. Soft-deleted comments are excluded.

Auth required: Yes (issues:read)

POST /v1/projects/:projectId/issues/:issueId/comments

Add a comment to an issue. Author is resolved from auth context (user JWT or agent API key).

Auth required: Yes (issues:write)

Request body

FieldTypeRequiredDescription
bodystringYesComment text. Markdown supported.

Returns 201 with the created comment.

PATCH /v1/projects/:projectId/issues/:issueId/comments/:commentId

Edit a comment. Only the original author can edit.

Auth required: Yes (issues:write)

Request body

FieldTypeRequiredDescription
bodystringYesUpdated comment text.

Returns 403 if the authenticated user/agent is not the original author.

DELETE /v1/projects/:projectId/issues/:issueId/comments/:commentId

Soft-delete a comment. The original author or a team admin/owner can delete.

Auth required: Yes (issues:write)

Returns { "deleted": true }.

GET /v1/issues

Team-level cross-project issue listing. Returns issues across all accessible teams (or a specific team via team_id). Mirrors the /v1/events pattern. Each issue is returned with a project_name in addition to the per-project response fields.

Auth required: Yes (issues:read permission or JWT)

Query parameters

ParameterTypeDescription
team_idstringFilter to a specific team.
project_idstringFilter to a specific project.
statusstringFilter by status: new, in_progress, resolved, silenced, regressed, snoozed.
app_idstringFilter to a specific app.
is_devstringFilter by dev mode: true or false.
data_modestringproduction (default), development, or all.
cursorstringCursor from previous response.
limitnumberItems per page (1-200, default 50).

Response

Same shape as GET /v1/projects/:projectId/issues, but each issue also includes a project_name field.

Ready to get started?

Connect your agent via MCP or CLI and start tracking.