Lookout

REST API (v1)

All paths below are rooted at https://lookout.dply.io/api. Send Accept: application/json and a JSON body on POST requests unless noted.

Machine-readable description: OpenAPI 3 — v1.yaml. Ingest POST bodies and rate limits are documented in the Ingest API.

Authentication

Personal access token (management & triage) — Create a token in Profile. Send it as a Bearer token:

Authorization: Bearer <your_sanctum_token>

For GET requests only, you may pass api_token=<token> as a query parameter when you cannot set headers (the app copies this into Authorization server-side).

These routes live under /api/v1/... and use the rest_api throttle: 120 requests per minute per authenticated user (by user id). Unauthenticated calls fall back to the client IP.

Project API key (ingest & key-scoped reads) — Same key as in project settings. Supported locations (see Ingest API): X-Api-Key, X-Api-Token, Authorization: Bearer, api_key in JSON body (POST), or ?api_key= on GET event listing.

If the organization configures an ingest IP allowlist, requests that fail the check receive 403.

Pagination

List endpoints accept either flat query parameters or JSON:API-style nested parameters:

Responses include meta with current_page, last_page, per_page, and total.

Sanctum — /api/v1

GET /api/v1/me

Current user id, name, email, organizations (with pivot role), and teams.

GET /api/v1/projects

Projects you can access, with organization embedded. Optional filter: filter[organization_id]= or organization_id=.

Each item includes api_key_prefix (first characters of the ingest key), not the full secret.

POST /api/v1/projects

Body: name (string), organization_id (ULID string, org you belong to), optional team_ids (team ULIDs / access groups in that org), optional tech_stacks (array of slugs from the project tech presets), optional environment_labels (strings you send as environment on ingest; defaults to production, staging, development, preview when omitted or empty). Returns 201 with the full api_key once; store it securely. 422 if the org is at its project limit.

GET /api/v1/projects/{id}

Single project (404 if not accessible). Includes api_key_prefix.

GET /api/v1/projects/{id}/errors

Grouped issues (one row per fingerprint). The id field is the representative occurrence ULID for that group—use it with occurrence and action routes below.

Query parameters (same semantics as the web UI):

GET /api/v1/projects/{id}/error-count

Returns {"data":{"count":N}} — number of groups matching the same filters as the grouped list.

GET /api/v1/projects/{id}/error-occurrence-count

Raw occurrence count for the project with optional filters: from, to (dates), or time as above, level, environment, release.

GET /api/v1/errors/{error}/occurrences

Paginated list of occurrences in the same fingerprint group as the given error id (or only that event when there is no fingerprint). Summary fields match the key-based events list.

GET /api/v1/error-occurrences/{id}

Full occurrence payload: stack trace, frames, context, breadcrumbs, exception chain, and tracing identifiers when present.

Triage (POST, JSON body optional)

Paths (replace {error} with a representative or any occurrence ULID in the group):

Project API key — read events

These routes accept the project key and only return data for the project that owns the key. Pagination uses page and per_page (max 100).

GET /api/projects/{project}/events

Optional query parameters: level, search (message substring), fingerprint, status, from, to, environment, release, correlation_id, parent_id (ULID of a parent error event), trace_id.

GET /api/projects/{project}/events/{event}

Single occurrence detail. Returns 404 if the event is not in the project; 403 if the key belongs to another project.

The same handlers are mounted at /api/v1/projects/....

Legacy

GET /api/me — minimal user json for older clients; prefer GET /api/v1/me.

Status codes