Skip to main content

App History

App history is the audit-style timeline for a single client app. It records lifecycle and approval activity such as discovery, approval status changes, and human-authored notes.

This is a child collection under an app because history is unbounded, time-ordered, and not always needed to render the primary App resource. See the Design Guidelines and App History Design Review.

Endpoints

EndpointMethodDescription
List HistoryGETPaginated app history timeline, newest first
Add NotePOSTAppend a note event to the app history timeline

Approval events are not created by posting directly to /history. They are created as side effects of the app approval endpoints:


DTOs

ActorRef

Small embedded actor projection used inside app history events.

{
"id": "1b8fbc0f-f234-4da7-9cb2-5ae10ef63b8e",
"display_name": "Jane Smith"
}
FieldTypeNullableDescription
idstring (uuid)NoStable unique identifier for the actor record
display_namestringNoHuman-readable name to render in the timeline UI

Notes:

  • This is intentionally not UserRef. App history actors currently come from the partner_users domain, not the client users domain.
  • System-generated events use actor: null.
  • If multiple actor domains are introduced later, this shape can be extended with type.

AppHistoryEvent

Single timeline event for a client app.

{
"id": "9f4f8c52-3d85-4d0f-bec3-d95e890d1d24",
"event_type": "approval_status_changed",
"actor": {
"id": "1b8fbc0f-f234-4da7-9cb2-5ae10ef63b8e",
"display_name": "Jane Smith"
},
"message": "approved this app",
"comment": null,
"metadata": {
"is_approved": true
},
"created_at": "2026-03-06T19:42:11.000Z"
}
FieldTypeNullableDescription
idstring (uuid)NoStable unique identifier for this history event
event_typestringNoEvent discriminator: app_created, approval_status_changed, note_added
actorActorRefYesActor who caused the event. null for system-generated events.
messagestringYesShort timeline copy owned by the API for event display
commentstringYesOptional free-text note or annotation attached to the event. Typically populated on note_added events.
metadataobjectYesEvent-specific structured data
created_atstring (ISO 8601)NoWhen the history event was created

Notes:

  • client_id and app_id are omitted because they are already present in the URL path.
  • Events are append-only.
  • Consumers must not infer business meaning from message text alone; use event_type and metadata.
  • App.is_approved and AppHistoryEvent.metadata.is_approved are intentionally different concepts:
    • App.is_approved is the app's current approval state
    • AppHistoryEvent.metadata.is_approved is the approval state produced by that specific history event

AppHistoryEvent.metadata

The metadata object is event-specific.

event_typemetadata shape
app_creatednull
approval_status_changed{ "is_approved": boolean }
note_addednull

List History

GET /clients/{client_id}/apps/{app_id}/history

Returns a paginated timeline of app history events ordered by created_at descending (newest first).

When to use

Use this endpoint to:

  • render the app detail timeline,
  • show approval changes over time,
  • display notes attached to the app,
  • inspect discovery and audit-style activity for a single app.

Path Parameters

ParameterTypeDescription
client_idstring (uuid)Unique identifier for the client organization
app_idstring (uuid)Unique identifier for the app

Query Parameters

ParameterTypeDefaultDescription
page_sizeinteger50Items per page. Each endpoint defines its own maximum.
cursorstring-Opaque cursor from a previous response

Response

FieldTypeDescription
dataAppHistoryEvent[]Array of history events, newest first
total_countintegerTotal number of events for this app
next_cursorstring | nullCursor for the next page. null when on the last page.

Example Request

curl -X GET "https://api.example.com/v2/clients/aa7cf840-9ca9-46a3-9778-9015d6580d50/apps/f1a2b3c4-d5e6-7890-abcd-ef1234567890/history" \
-H "Authorization: Bearer YOUR_API_TOKEN"

Example Response

{
"data": [
{
"id": "9f4f8c52-3d85-4d0f-bec3-d95e890d1d24",
"event_type": "approval_status_changed",
"actor": {
"id": "1b8fbc0f-f234-4da7-9cb2-5ae10ef63b8e",
"display_name": "Jane Smith"
},
"message": "approved this app",
"comment": null,
"metadata": {
"is_approved": true
},
"created_at": "2026-03-06T19:42:11.000Z"
},
{
"id": "81ab9698-7837-43c1-8b89-6b3118b8b1f2",
"event_type": "note_added",
"actor": {
"id": "1b8fbc0f-f234-4da7-9cb2-5ae10ef63b8e",
"display_name": "Jane Smith"
},
"message": "added a note",
"comment": "Waiting for security sign-off",
"metadata": null,
"created_at": "2026-03-05T17:15:00.000Z"
},
{
"id": "d14a4cb9-b1e4-4fb9-b459-d4aaf7b0e1df",
"event_type": "app_created",
"actor": null,
"message": "App was discovered in your account",
"comment": null,
"metadata": null,
"created_at": "2026-02-18T09:00:00.000Z"
}
],
"total_count": 3,
"next_cursor": null
}

Pagination

This endpoint uses cursor-based pagination.

  1. Omit cursor on the first request
  2. If next_cursor is not null, pass its value as cursor on the next request
  3. Repeat until next_cursor is null

Error Responses

StatusDescription
400Invalid request (e.g. invalid UUID, malformed cursor)
401Authentication required
403Insufficient permissions for this client
404App or client not found
500Server error

Example Error Response

{
"error": {
"code": "not_found",
"message": "App not found",
"details": {
"app_id": "f1a2b3c4-d5e6-7890-abcd-ef1234567890"
}
}
}

Notes

  • History is returned newest first.
  • Events are append-only.
  • Approval endpoints append approval_status_changed events as side effects.
  • Approval events typically carry metadata.is_approved and comment: null.
  • metadata.is_approved on a history event is not a duplicate of App.is_approved; it records the outcome of that event, while the app resource shows the current state.
  • actor is a small embedded ref for rendering the timeline, not a full user DTO.
  • If the API is intended to serve as a strict audit trail, actor.display_name should be snapshotted at write time rather than resolved dynamically.