---
title: "Read the app's durable runtime-failure events"
method: GET
path: "/app/{id}/activity"
---

# Read the app's durable runtime-failure events

`GET /app/{id}/activity`

## Request

- Base URL: `https://charm.ing`
- URL: `https://charm.ing/app/{id}/activity`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer

Owner-only. Returns the app's own `api_proxy_result`, `visitor_calls_refused` (calls from people who are not members, refused at their limits and summarized per 10 seconds; not runtime failures), `image_proxy_result` (external image failures), `diag_report` (runtime JS errors, CSP violations), `contract_validation`, `app_load_error`, and `render_token_revoked` events from durable storage — use this after publishing to learn what broke at runtime. Unlike `GET /app/{id}/diag` (in-memory ring buffer, always lost on deploy), these rows are meant to survive deploys, but most kinds here are telemetry the server can shed under sustained load rather than block a request on: `api_proxy_result` and `render_token_revoked` at the telemetry lane's in-flight write budget, and `diag_report`, `image_proxy_result`, `app_load_error` in the in-process queue those flood-prone kinds share. Only `contract_validation` (and the audit kinds this endpoint does not return) write synchronously and are never shed. Requires the app token or the owner's user token; render tokens and claim cookies are rejected. Not to be confused with `GET /app/{id}/events`, the live-state SSE stream.

## Query parameters

- `kinds` string
- `since` string, date-time
- `limit` integer

## Response `200`

Newest-first runtime-failure events

- ActivityResponse
  - `ok` true, required
  - `value` object, required
    - `retention` object, required: The plan window this read used: 24 hours on Free, 30 days on Pro, 90 days on Business. Older events are hidden, not deleted.
      - `tier` 'free' | 'pro' | 'business' | 'enterprise', required
      - `hours` integer, required: Length of the plan window.
      - `since` string, date-time, required: The cutoff this read used.
      - `truncated` boolean, required: True when the plan window set the cutoff.
    - `items` object[], required: Newest-first durable runtime-failure events for this app, inside the plan window. Bounded by per-kind insert caps and a 90-day prune.
      - `ts` string, date-time, required
      - `kind` 'api_proxy_result' | 'visitor_calls_refused' | 'image_proxy_result' | 'diag_report' | 'contract_validation' | 'app_load_error' | 'render_token_revoked', required
      - `revision` integer, required: Server-owned app source revision. New apps start at 1, each successful source write advances it once, and historical null counters project as 0. `If-Match: "<N>"` and `expected_revision` carry this revision through its canonical concurrency grammar.
      - `summary` string, required: Compact one-line description of the event.
      - `data` object, required: Kind-specific redacted payload (no stacks, no tokens, no source bytes).

## Other responses

- `400`: Invalid app id, unknown kind, or malformed since/limit.
- `401`: Authentication required (render tokens and claim cookies rejected).
- `403`: Token does not authorize this app.
- `404`: App not found.

---

[API](https://skmtc.dev/charm/apis/charming-api.md) · [All operations](https://skmtc.dev/charm/apis/charming-api/llms.txt) · [OpenAPI document](https://skmtc.dev/charm/apis/charming-api/revisions/a9d06c419b3a?raw)
