Topolo Docs Topolo Platform
Open workspace

List workspace offers — Campaigns

Lists stored offers in the bound organization/workspace, newest update first. Reading an offer does not establish that any campaign or code uses it.

List workspace offers

Lists stored offers in the bound organization/workspace, newest update first. Reading an offer does not establish that any campaign or code uses it.

Outcome and boundaries

Lists stored offers in the bound organization/workspace, newest update first. Reading an offer does not establish that any campaign or code uses it.

Before you start

  • Confirm the intended environment and current credential organization using whoami; discover the exact application/action before any call.
  • Required application permission: app_topolo_campaigns.offers:read. Catalog discoverability is not permission to execute.
  • Discover an authorized canonical workspace and bind resourceType workspace/resourceId separately from action input.
  • All worked cases in this guide are hypothetical source-reviewed illustrations; no business action, live fixture, customer data or provider request was executed.
  • Canonical workspace minimum access is read in addition to the application permission. After grant verification, the first request may create an app-local identity/recipient mirror even before the later app-permission check; this is not campaign-domain completion.

Discover the intended identifiers

  • Discover a granted workspace; this action takes no campaign id.

Action: app_topolo_campaigns.offers.list · GET /api/offers.

Input fields

No input fields. Send {}. Any published resource context remains separate from this object.

Safe call sequence

Write the reviewed input to payload.json; fixture identifiers below are unusable examples. Validate before planning, bind the discovered resource separately, and execute only within actual authority.

topolo actions validate app_topolo_campaigns.offers.list --data @payload.json --json
topolo actions plan app_topolo_campaigns.offers.list --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json

A published read can use topolo actions call with the same discovered resource and input. This guide does not invoke it.

Worked cases

Every response below is synthetic and source-reviewed, not captured. HTTP status and body are explained independently; a structurally valid body alone never proves successful execution. Middleware may add a different error envelope.

One stored offer · HTTP 200

Input:

{}

Illustrative response:

{
  "offers": [
    {
      "id": "offer_example",
      "kind": "discount_pct",
      "value": 15,
      "label": "Illustrative 15 percent",
      "rules": {},
      "createdAt": "2026-10-20T00:00:00.000Z",
      "updatedAt": "2026-10-20T00:00:00.000Z"
    }
  ]
}

Empty workspace · HTTP 200

Input:

{}

Illustrative response:

{
  "offers": []
}

Permission refusal · HTTP 403

Input:

{}

Illustrative response:

{
  "error": "forbidden"
}

Verify the outcome

  • Inspect offers[].id, kind, value, label and rules. Use a returned id when creating or updating a campaign.

Refusals and recovery

  • HTTP 403 forbidden: Raw handler permission refusal. SDKs can normalize it to permission_denied. Keep the same intended resource; do not widen access.
  • HTTP 403 workspace_forbidden: The canonical workspace grant refused the selected resource. Resolve it with the access owner, not a guessed workspace.

No campaign-domain rollback is needed for this read. Preserve authentication, permission and resource refusals; do not switch organization or widen a grant to bypass them.

Exact schemas and provenance

Input schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {},
  "additionalProperties": false
}

Output schema:

{
  "title": "List offers response",
  "description": "Collection response returned by offers.list. The service may return the collection directly or in an envelope.",
  "oneOf": [
    {
      "type": "array",
      "items": {
        "type": "object",
        "title": "offer record",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier when the offer exposes one."
          }
        },
        "additionalProperties": true
      }
    },
    {
      "type": "object",
      "properties": {
        "data": {
          "oneOf": [
            {
              "type": "array",
              "items": {
                "type": "object",
                "title": "offer record",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Stable identifier when the offer exposes one."
                  }
                },
                "additionalProperties": true
              }
            },
            {
              "type": "object",
              "additionalProperties": true
            }
          ]
        },
        "items": {
          "type": "array",
          "items": {
            "type": "object",
            "title": "offer record",
            "properties": {
              "id": {
                "type": "string",
                "description": "Stable identifier when the offer exposes one."
              }
            },
            "additionalProperties": true
          }
        },
        "offers": {
          "type": "array",
          "items": {
            "type": "object",
            "title": "offer record",
            "properties": {
              "id": {
                "type": "string",
                "description": "Stable identifier when the offer exposes one."
              }
            },
            "additionalProperties": true
          }
        },
        "count": {
          "type": "integer",
          "minimum": 0
        },
        "nextCursor": {
          "type": [
            "string",
            "null"
          ]
        }
      },
      "additionalProperties": true
    }
  ],
  "x-topolo-contract-source": "derived-action-metadata",
  "x-topolo-contract-precision": "structural"
}

Reviewed immutable source: TopoloCampaigns@cacbb8b12b4e19a662cf82d03a927aef3c3a35e8, apps/api/src/campaigns-store.ts. Fresh production catalog was read on 2026-10-20. Its publication metadata is not proof that this source is loaded. Output examples are not widened or rewritten to force schema success; the accompanying validation record classifies exact success, refusal, no-body and structural-schema limits.

  • Create a draft campaign — Campaigns: Creates one draft campaign. Optional offerId must resolve in the selected organization/workspace. Creating it neither activates redemption nor issues codes.
  • Update or activate a campaign — Campaigns: Changes campaign name, offer or draft/active/paused/archived status. Activation allows existing active codes to validate/redeem; it does not issue or distribute codes.

Local input rejection example

This deliberately invalid input belongs to a pure schema check; it is never a planned or executed request. The closed action input schema must reject the extra field. It has no HTTP status or server response.

{
  "__unsupported_field": true
}

The hidden companion labels this as ILLUSTRATIVE_LOCAL_SCHEMA_CHECK; its validation representation is not an action output.

Published output validation limits

Current published output qualification: the output schema accepts an empty object, a partial success marker, a partial data object and a refusal body. It therefore establishes only broad structure. Require the documented HTTP/domain result and source-shaped fields; missing fields or a schema-valid error are not success. The current oneOf array/object branches have disjoint types, including the nested data branches; no oneOf ambiguity was observed. Their missing required collection fields still permit empty or partial objects.

These observations come from pure checks of the exact published schema; they are not server responses or production captures.