Topolo Docs Topolo Platform
Open workspace

Connect event delivery

Create missing tracked subscriptions for the organization’s Nexus email event types using the verified organization admin’s Notify authority. Locally active types are skipped. Creation and cleanup cross service boundaries: a failure does not guarantee that nothing changed, and disconnection is a separate operation rather than an automatic inverse.

Before you start

  • Use production unless development or staging is explicitly scoped, and keep the same authorized organization throughout. Reading this guide does not execute an action.
  • Discover the current published action and validate/plan exact input before any later execution. Confirm the actual mutation and its provider/audit effects.
  • Required published permission: app_topolo_engage.workspace:write.
  • Select the organization resource separately from action input. Mutations require the verified organization admin’s own bearer and Notify webhook-management authority; service credentials are not a substitute. Status itself does not call the mutation-only ready guard.

Effects and limits

  • Creates a Notify webhook subscription for each missing Nexus email event type with the organization's derived signing secret.

  • On create failure, cleanup of already created Notify subscriptions is best effort. Failed cleanup or a lost response can leave external effects without complete local rows; local absence does not prove no external subscription.

  • Connecting also retires locally tracked active legacy event types: Notify removal is best effort, then the local legacy row is revoked. This can happen even when created is false; local revocation does not prove the remote legacy subscription was removed.

Request

POST /api/events/delivery/connect

Inputs below are source-derived synthetic examples, not approval to execute. Discover resource context separately.

Input fields

FieldRequiredType and constraints
No body fields—Use the empty object {}; keep organization selection outside the body.

Worked examples

Every request/response below is synthetic and unrun, authored from reviewed source and retained published schemas. It is not a captured local or production response. Fixture identities and timestamps authorize nothing.

Create missing subscriptions

SOURCE-DERIVED SYNTHETIC UNRUN example. This is authored illustration, not a captured response, live authorization, provider result or test pass.

Request:

{}

Response illustration:

{
  "delivery": {
    "connected": true,
    "status": "active",
    "eventTypes": [
      {
        "eventType": "nexus.email.delivered",
        "status": "active",
        "notifySubscriptionId": "whsub_example_1",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.bounced.hard",
        "status": "active",
        "notifySubscriptionId": "whsub_example_2",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.bounced.soft",
        "status": "active",
        "notifySubscriptionId": "whsub_example_3",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.complained",
        "status": "active",
        "notifySubscriptionId": "whsub_example_4",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.replied",
        "status": "active",
        "notifySubscriptionId": "whsub_example_5",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.auto_reply",
        "status": "active",
        "notifySubscriptionId": "whsub_example_6",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.unsubscribed",
        "status": "active",
        "notifySubscriptionId": "whsub_example_7",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      }
    ]
  },
  "created": true,
  "results": [
    {
      "eventType": "nexus.email.delivered",
      "outcome": "created"
    },
    {
      "eventType": "nexus.email.bounced.hard",
      "outcome": "created"
    },
    {
      "eventType": "nexus.email.bounced.soft",
      "outcome": "created"
    },
    {
      "eventType": "nexus.email.complained",
      "outcome": "created"
    },
    {
      "eventType": "nexus.email.replied",
      "outcome": "created"
    },
    {
      "eventType": "nexus.email.auto_reply",
      "outcome": "created"
    },
    {
      "eventType": "nexus.email.unsubscribed",
      "outcome": "created"
    }
  ]
}

Compare every returned event type with a same-organization status read. Source skips locally active types; this is not a concurrent/provider idempotency guarantee.

Reconnect when current types are already locally active

SOURCE-DERIVED SYNTHETIC UNRUN example. This is authored illustration, not a captured response, live authorization, provider result or test pass.

Request:

{}

Response illustration:

{
  "delivery": {
    "connected": true,
    "status": "active",
    "eventTypes": [
      {
        "eventType": "nexus.email.delivered",
        "status": "active",
        "notifySubscriptionId": "whsub_example_1",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.bounced.hard",
        "status": "active",
        "notifySubscriptionId": "whsub_example_2",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.bounced.soft",
        "status": "active",
        "notifySubscriptionId": "whsub_example_3",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.complained",
        "status": "active",
        "notifySubscriptionId": "whsub_example_4",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.replied",
        "status": "active",
        "notifySubscriptionId": "whsub_example_5",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.auto_reply",
        "status": "active",
        "notifySubscriptionId": "whsub_example_6",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      },
      {
        "eventType": "nexus.email.unsubscribed",
        "status": "active",
        "notifySubscriptionId": "whsub_example_7",
        "createdBy": "user_original_example",
        "createdAt": "2026-10-20T00:00:00.000Z",
        "rotatedAt": null
      }
    ]
  },
  "created": false,
  "results": [
    {
      "eventType": "nexus.email.delivered",
      "outcome": "existing"
    },
    {
      "eventType": "nexus.email.bounced.hard",
      "outcome": "existing"
    },
    {
      "eventType": "nexus.email.bounced.soft",
      "outcome": "existing"
    },
    {
      "eventType": "nexus.email.complained",
      "outcome": "existing"
    },
    {
      "eventType": "nexus.email.replied",
      "outcome": "existing"
    },
    {
      "eventType": "nexus.email.auto_reply",
      "outcome": "existing"
    },
    {
      "eventType": "nexus.email.unsubscribed",
      "outcome": "existing"
    }
  ]
}

Current locally active types are skipped, but this remains a mutation: legacy tracked rows may be retired even when created is false. Local revocation does not prove remote legacy removal; no concurrency/provider idempotency guarantee is established.

A Notify failure can follow partial or uncertain effects

SOURCE-DERIVED SYNTHETIC UNRUN example. This is authored illustration, not a captured response, live authorization, provider result or test pass.

Request:

{}

Response illustration:

{
  "error": {
    "code": "notify_unavailable",
    "message": "Notify could not be reached. Try again.",
    "details": {
      "eventType": "nexus.email.bounced.hard"
    }
  }
}

Retain the failing eventType and reconcile both local state and separately authorized Notify state. Do not infer nothing changed or blindly repeat.

Verify the result

  • Call events.delivery.status and check delivery.status and each eventTypes[].status.
  • The status read is a local projection only; separately authorized provider checks are required for remote consistency. This guide neither performs them nor grants extra permission.

Errors and recovery

  • 401 user_credential_required: Call it as a signed-in organization admin, not with an app or service token.
  • 403 notify_admin_required: Ask an organization admin with app_topolo_notify.webhooks:manage to run it.
  • 403 permission_denied: Stop and ask the authorized application owner to review the exact permission requirement; do not automatically widen scopes or change context.
  • 409 event_delivery_not_connected: Connect event delivery first.
  • 422 notify_refused: Inspect the structured eventType/notifyCode, preserve possible partial effects and reconcile current local/remote state before any separately authorized retry. The source does not support a blanket nothing-changed assertion.
  • 502 notify_unavailable: Inspect the structured eventType/notifyCode, preserve possible partial effects and reconcile current local/remote state before any separately authorized retry. The source does not support a blanket nothing-changed assertion.
  • 503 event_delivery_not_configured: The deploy lacks ENGAGE_EVENT_SECRET_KEY, TOPOLO_NOTIFY_URL or ENGAGE_APP_URL.

No safe automatic inverse is published. After failure or response loss, preserve the exact action/error/eventType and read local events.delivery.status in the same organization, then reconcile remote Notify effects through its current authorized read contract with the owner. Local rows or a failed compensation do not prove no change. Never blindly connect/rotate/disconnect to test recovery or widen credentials. Any further mutation needs its own reviewed intent.

Evidence and change log

  • 2026-10-20: Prepared this paired guide from source 767d2d83713809e984559eee562a2c9f7ffcfa4d and the retained production contract snapshot. Independent source/content/audience review is complete. Examples remain explicitly synthetic and unrun; no original response capture or business execution is claimed.
  • Source-reviewed guidance preserves partial/uncertain subscription effects and local-only status; current catalogue recovery/scope/actor wording is under owner review.

Published contract wording under review

The retained catalogue description/recovery text includes stronger no-change or automatic-undo wording than this source supports. The published schema annotations are retained exactly for comparison; they are not a guarantee that compensation or provider delivery succeeds. Follow the source-qualified limits above.

Exact published-field qualifications

  • /outputSchema/properties/delivery/properties/eventTypes/items/properties/createdBy/description: Source-qualified limit: createdBy is the stored connection creator for that row, not the rotation actor. A later rotatedAt does not identify who rotated it.
  • /outputSchema/properties/delivery/properties/connected/description: Source-qualified limit: connected classifies whether all seven current local rows are active. It does not prove remote subscription existence, health, signature agreement or event delivery.
  • /outputSchema/properties/delivery/properties/status/description: Source-qualified limit: status classifies the seven current local rows only. not_connected is not proof that the organization has never connected in the past; legacy rows are excluded from this view.

The original published schema annotations remain evidence under review. Validation types/enums are unchanged; these guide qualifications do not assert a corrected catalogue publication or remote state.