publ betaReference (MCP guide)
Open publ console

Legacy promotion links

# Legacy promotion links

This is the original promotion-link tab under conversion links. It has its own IDs, keyword rules, creation quota, share base and legacy-promotion-link tasks. It is separate from newer conversion links and promotion campaign/benefit management.

| Need | Tool |
| --- | --- |
| Read all-list/counters/quota or one editor record | [legacy_promotion_links_get](../tools/publ_legacy_promotion_links_get.md) |
| Create or edit sharing metadata/thumbnail | [legacy_promotion_link_apply](../tools/publ_legacy_promotion_link_apply.md) |
| Delete one selected non-default link | [legacy_promotion_link_delete](../tools/publ_legacy_promotion_link_delete.md) |

OWNER or DELEGATEE requires MANAGE_CONVERSION_LINKS. Source hosted account resources exclude these operations; an authorized channel resource must match channelCode exactly. Default cards are read-only, even with positive IDs. Activation, bulk mutation, QR export and detailed associated-page editing are not exposed.

## Read and compose

Read the bounded source all-list and its quota. No invented pagination or certified server inventory completeness is provided. If the optional statistics service is unreachable or returns 5xx, verified metadata remains available with partial:true and unavailable statistics; each returned linkTime is null. Zero applies only to a missing row in a valid statistics response. Do not treat an outage as permission to bypass quota or as zero visits.

```json
{
  "channelCode": "selected-channel-code",
  "view": {
    "kind": "list"
  }
}
```

Use creationRevision for a complete create request. For update/delete, read the selected positive numeric id and use its detail revision. The following plan checks quota/content but does not check keyword availability or create a task. Replace the zero digest; omitted dryRun defaults to false.

```json
{
  "channelCode": "selected-channel-code",
  "requestId": "legacy-create-01",
  "action": "create",
  "expectedRevision": "0000000000000000000000000000000000000000000000000000000000000000",
  "settings": {
    "name": "Autumn promotion",
    "title": "See our latest content",
    "description": "Explore the channel.",
    "keyword": "autumn_2026"
  },
  "dryRun": true
}
```

Actual creation checks keyword availability and quota/inventory before image work and again before submission. Neither is an atomic reservation. Update edits name/title/description and optional original thumbnail; omission preserves the baseline. Keyword and associated page/membership targets remain read-only. Do not identify an uncertain creation by name or keyword.

## Creation quota

The fixed source policy distinguishes known dev/prod API origins from custom deployments:

| Source plan | Maximum returned link rows |
| --- | --- |
| FREE_TRIAL | 0 |
| NORMAL_STARTER, NORMAL_STARTER_2023_04 | 1 |
| NORMAL_BASIC | 2 |
| NORMAL_ESSENTIAL | 3 |
| NORMAL_BUSINESS, NORMAL_FROM_ENTERPRISE, NORMAL_PRO | 5 |
| ENTERPRISE_TRIAL, ENTERPRISE_ENTERPRISE | 5 |
| PARTNER_TRIAL, PARTNER_PARTNER, INTERNAL_INTERNAL | 5 |

Three explicit source channel exceptions override those limits only for the recognized production API deployment; they do not apply to dev/custom origins. Read returned quota rather than reproducing private channel identifiers. Outside those configured production exceptions, an unknown/missing plan yields limit:null. Every custom API origin yields an unknown limit. currentCount includes all returned rows/default cards. A new plan with unknown/exhausted capacity returns action_required and one human plan console destination. The bridge never purchases or changes a plan. Existing-link reads/update/delete do not require spare creation capacity.

## Images and recovery

Original PNG/JPEG thumbnails must be below10,000,000 decimal bytes. Omission preserves an existing image; null removal and URL replacement are unsupported. Resource gateway/bucket/region must be configured, and only verified original-byte upload receipts enter saves. Separate grant/upload/save effects have no rollback or object cleanup. Journals retain metadata, not bytes or temporary credentials.

Use the returned taskId and taskType legacy-promotion-link:

```json
{
  "taskId": "legacy-create-01",
  "taskType": "legacy-promotion-link"
}
```

Status is historical; resume may continue untouched stages after guards. Sent create/update/delete/grant/upload effects never repeat. An unstarted image after restart needs original apply bytes; a sent grant/upload without a receipt needs inspection. Missing durable creation identity is not adopted by name/keyword. Only linkTime is excluded from legacy preservation: do not assume the newer conversion workflow's timestamp tolerance applies. Read again after completion for current state.

Delete requires DELETE_LEGACY_PROMOTION_LINK and should first be planned.

## Share base and console locations

Configure legacyPromotionLinkBaseUrl or PUBL_LEGACY_PROMOTION_LINK_BASE_URL separately from conversionLinkBaseUrl. Use the actual environment's HTTPS base ending in /, without credentials/query/fragment. A custom API override does not inherit another profile's base. Returned safe keywords are encoded as a path component; default cards and unconfigured/demo output have no share URL. No destination is fetched and no redirect/attribution is certified.

Console navigation uses `/channels/{channelCode}/conversion-links/promotion-links`, its `/create` child or `/{id}/edit`; there is no invented detail page. Default cards/deletion return the list.