Topolo Docs Topolo Platform
Open workspace

Browse notification definitions

Filter saved notification definitions and projections with actual cursor pagination, clear direct response examples and separate execution/permission boundaries.

Outcome

Browse saved notification definitions and projections with filters and cursor pagination, keeping catalogue metadata separate from event or message execution.

GET /api/catalog/notifications

Before you start

This published catalogue action is public and declares no application permission. Its handler performs no credential/context grant; reading definitions does not authorize subscribing, emitting, provisioning, sending, accessing private records or using a referenced action. Discover each later operation independently.

Use q,app,status,deliveryClass,limit,cursor exactly as the current native schema allows. A real continuation cursor must come from the preceding matching response; keep the same filters and do not fabricate one from a display label.

Worked examples are complete source-derived synthetic UNRUN catalogue responses from explicitly fictional saved manifests. No public/private event, subscription, recipient, sender, message or business action was queried or executed; no application import/test/runtime probe was run.

Filters and response

Action: app_topolo_developers.notifications.catalog.list.

The HTTP200 body is directly {notifications,count,page:{hasMore,nextCursor}}. This handler does not wrap it in success/message/data. count is the selected page length, not a global total, delivery count or complete event inventory.

The source loads directory pages of up to100 apps with includeAll:true and hydrates their saved published manifests before applying notification filters/pagination. This path does not itself enforce marketplace-public or non-sunset filtering. Endpoint publicity is not a guarantee that every represented app/event is currently listed, active or callable. No live data-exposure assessment is established by this source review.

Limit defaults25 and is capped100. Native input requires an integer1-100; do not rely on HTTP parseInt/default/clamp behaviour to bypass the published schema. Returning one page bounds response size, but not the initial full-manifest scan/hydration work.

Each entry contains app:{appId,slug,displayName}, registryDigest (saved notifications.registryDigest or null), event (saved object), and projection (first matching catalog projection or null). Event/projection objects preserve their saved fields, not a new fully validated runtime contract. Nonobject saved entries become empty objects.

Projection selection requires exact event type and exact version equality. An integer and string version do not match. The deliveryClass filter compares that selected projection; an event without matching projection is excluded by a nonempty deliveryClass filter. registryDigest is saved metadata, not a fresh dispatch receipt or re-computed delivery proof.

app matches exact appId or slug. status compares exact saved event.status; deliveryClass compares exact saved projection.deliveryClass. q is trimmed/case-insensitive substring search over app displayName/slug and event type/description only. Missing filters do not default to only published event status; draft/deprecated definitions may appear. Native status/deliveryClass enums govern admitted input.

Results sort lexicographically by app slug, event type and String(version).padStart(10,"0"), joined with vertical bars. Cursor comparison is strict greater-than. page.hasMore uses remaining length>limit, and nextCursor is the final selected tuple only when more rows remain, otherwise null. Do not treat the version padding as semantic-version ordering or the cursor as authorization.

There is no cross-page snapshot token or explicit unique-event identity tiebreak beyond that tuple. Concurrent catalogue changes or duplicate tuples can affect traversal. The source checks internal app-directory cursor advancement and hydration generation coherence, but this is not a global multi-app snapshot or guarantee every event is uniquely paginated.

A missing/invalid saved application manifest or hydration-generation mismatch throws instead of silently certifying an empty catalogue. Preserve actual status/error/request details; source here does not provide a uniform structured catch/error envelope to invent. GET success is definition discovery only; OPTIONS204 is preflight, not a catalogue result.

Worked requests and responses

No definitions match the query

Complete synthetic UNRUN HTTP200 assuming no matching saved definition across the loaded fixture manifests. It is the direct body, without success/data. No event or message was emitted.

Input:

{
  "q": "missing-fixture-definition"
}

Response:

{
  "notifications": [],
  "count": 0,
  "page": {
    "hasMore": false,
    "nextCursor": null
  }
}

Read count0 and page.hasMore:false for this query only; do not infer the platform has no other events.

Read the first definition page

Complete synthetic UNRUN HTTP200 assuming exactly two saved fixture definitions, created then updated, each with the shown first matching projection. The null digest is saved metadata; none is fabricated as a receipt.

Input:

{
  "app": "fixture",
  "status": "published",
  "deliveryClass": "notification",
  "limit": 1
}

Response:

{
  "notifications": [
    {
      "app": {
        "appId": "app_docs_fixture",
        "slug": "fixture",
        "displayName": "Fixture"
      },
      "registryDigest": null,
      "event": {
        "type": "fixture.created",
        "version": 1,
        "status": "published",
        "description": "Fictional created notification definition."
      },
      "projection": {
        "event": "fixture.created",
        "version": 1,
        "deliveryClass": "notification"
      }
    }
  ],
  "count": 1,
  "page": {
    "hasMore": true,
    "nextCursor": "fixture|fixture.created|0000000001"
  }
}

Keep the exact filters and use the returned cursor if continuing. A published definition does not prove any delivery or subscription authority.

Continue the same filtered catalogue

Complete synthetic UNRUN HTTP200 with exactly the unchanged two-definition fixture from the previous page. This demonstrates continuation, not an instruction to manufacture a real cursor or assume a live cross-page snapshot.

Input:

{
  "app": "fixture",
  "status": "published",
  "deliveryClass": "notification",
  "limit": 1,
  "cursor": "fixture|fixture.created|0000000001"
}

Response:

{
  "notifications": [
    {
      "app": {
        "appId": "app_docs_fixture",
        "slug": "fixture",
        "displayName": "Fixture"
      },
      "registryDigest": null,
      "event": {
        "type": "fixture.updated",
        "version": 1,
        "status": "published",
        "description": "Fictional updated notification definition."
      },
      "projection": {
        "event": "fixture.updated",
        "version": 1,
        "deliveryClass": "notification"
      }
    }
  ],
  "count": 1,
  "page": {
    "hasMore": false,
    "nextCursor": null
  }
}

Stop because hasMore:false, retaining source/filter context. Discover any real subscription/emission/action through its own current contract and authority.

Verify and recover

  1. Check the direct notifications/count/page body and compare selected app, event type/version/status, projection and saved digest. Never reinterpret these definitions as delivered messages or resource grants.

  2. Follow actual nextCursor only while hasMore is true, keeping filters fixed. If a cursor fails to advance or duplicate tuples/concurrent changes make completeness uncertain, retain that limitation rather than claiming an exhaustive snapshot.

  3. For an intended operation, separately discover the actual app/action/resource, current permission and supported input, then verify at its proper execution boundary. Public event catalogue metadata does not authorize subscription, emission, provider delivery or private data access.

  4. No inverse is needed for this catalogue read. After an actual read error, preserve the real error/status; do not invent empty success, retry unchanged mutations or probe unrelated private operations.

Change log

  • 2026-10-21: Added direct response shape, exact filter/projection semantics, cursor/page limits, saved metadata and full-scan/snapshot limitations, with three complete synthetic unrun examples.