> ## Documentation Index
> Fetch the complete documentation index at: https://docs.extole.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Validate and Publish an Integration

> Gate Extole to Partner resources, validate the finished shape, publish the validated version, and connect the integration to a program.

Part of the [partner integration guide](/technical/building-partner-integrations/integration-lifecycle/management-api-integration).

# Overview

Validation is the last gate before an integration goes live: decide whether it should own Extole to Partner resources, check the built shape against the model, then publish the version you checked. Connecting its business events to a marketing program is a separate, approved step.

## Gate Extole to Partner Resources

This applies to a Partner to Extole build someone proposes to extend in the other direction; the webhooks and credential a maintained Extole to Partner install ships with are part of its finished shape, not gated here.

Create Extole to Partner resources only when all of these hold:

* The requested scope includes a defined Extole to Partner use case.
* A program action or reward rule produces the event or reward.
* The destination endpoint and authentication contract exist.
* Retry, idempotency, error handling, and ownership are defined.
* The integration or program has a configuration surface for required values.
* The path can be tested before it is enabled.

A reward supplier models fulfillment inventory and a webhook is the HTTP transport, so a reward-supplier socket alone does not connect a partner; either without the rest of the program wiring leaves unused external resources.

When Extole to Partner scope is later removed, archive resources in dependency order:

1. Disable the webhook.
2. Remove its filters and component references, then archive it.
3. Remove reward-supplier references from rules and components, then archive the supplier.
4. Remove and archive the client key once no active references remain.
5. Remove unused component settings and sockets.
6. Publish and verify the resulting campaign.

## Validate Before Publishing

Read the latest campaign and its built components, then confirm:

### Campaign and Component Identity

* Campaign type is `INTEGRATION` and program type is `integration`.
* The root and integration model components exist, the model component carrying an `integration-v10.x` type.
* Where the build must appear as an installed integration, its owner and tags match what [Build a Partner Integration with the Management API](/technical/building-partner-integrations/integration-lifecycle/management-api-integration) describes; read the tags back.
* No unrequested reward supplier, webhook, client key, or socket exists.
* No legacy custom controller duplicates a reusable business event.
* Read from `/v1/components/built`, every webhook's `enabled` resolves to the integration's own toggle rather than to a literal `false`. A webhook holding a literal `false` never starts, regardless of what the installer does. Confirm every use case the integration promises has a webhook that can fire.

### Events and Data

* `businessEvents` accepts `business-event-v10.0`, and each canonical event is a duplicated reusable template.
* Every partner wire event in scope reaches a business event, and no two outcomes a report needs apart share one.
* Each event has an `input_event` rule carrying the partner event names, or the names a prehandler produces — not the canonical names, since a rule listening for `converted` matches every `converted` event in the account.
* Each event has its own reporting names: no two share a noun or rate name, and no alias appears on more than one.
* Every business event has data components in its `data` socket, each with the intended source expression and key type.
* Every event carries an email address, or an identity the account can reach. Where a prehandler flattens the payload, confirm the email is among its emitted keys.

### Reachability

* Whoever sends the partner event can send the shape the rules expect. Where the sender is the partner's own webhook, a prehandler exists, is `enabled`, carries at least one condition, and is referenced to the integration component — a disabled prehandler, or one with no conditions, passes every structural check here and leaves the integration inert. Read the evaluated `order` where more than one participates ([Normalize Partner Events with a Prehandler](/technical/building-partner-integrations/integration-types/partner-events-prehandlers)).
* Whoever configures the partner is given the endpoint: the configuration view's setup instructions render the URL the partner posts to, computed from the campaign, rather than naming the event endpoint without producing it.

### Views

* `views` accepts `view-v10.0`, and the configuration view is attached to the model component with `settingsToDisplay` referencing existing parent settings.
* The socket holds the three baseline views, plus the `reward-suppliers` configuration view on a reward fulfillment build.
* Read from `/v1/components/built`, `reportRunnerId` on the report-runner view and `eventStreamId` on the event-stream view each resolve to an identifier rather than null — a null means the element was never created, or was attached to the integration component instead of the view that reads it, and neither fails loudly.
* Every column named in `reportColumnsMapping` is one the report runner's `mappings` expression produces, and the event stream carries its filters.

### Display Settings

Read all eight display settings from `/v1/components/built` and check each against the value convention in [Create the Integration Campaign and Component Model](/technical/building-partner-integrations/integration-lifecycle/integration-component-model). Present is not usable: `short.description` and `about` describe this partner rather than integrations generally, `documentation.url` points at the partner-facing page rather than this build guide, and `categories` spells a string other integrations already use.

`logo` on the integration component and `rewardSupplierLogo` on every supplier template each hold an absolute URL. An empty value, or one still showing a `spel@buildtime:` expression, renders the grey placeholder tile.

### Publish the Validated Version

Publish the version you validated:

```bash theme={null}
curl --request POST \
  "$EXTOLE_API_HOST/v2/campaigns/$CAMPAIGN_ID/version/$CAMPAIGN_VERSION/publish" \
  --header "Authorization: Bearer $MANAGEMENT_API_ACCESS_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{}'
```

<Warning>
  A successful publish is model validation, not end-to-end verification. Nothing above proves an event reaches a step, and two pieces this guide creates — a prehandler script and a data component's `valueExpression` — are stored without ever being executed. Send a real payload and read the resulting step before you call the integration working.
</Warning>

## Connect the Integration to a Program

A finished integration turns partner events into business events inside its own campaign, while the account's marketing programs still run on the events their theme shipped with. Until the two are joined, the integration produces activity no program acts on.

Close the build by proposing two things, and do neither without an answer:

1. Publish the integration campaign, which makes the event endpoint accept events.
2. Install the integration's business events into a marketing campaign.

For the second, name the campaign candidates and list the partner events by canonical name, saying whether each supersedes an event the program has or adds one it lacks. A partner `converted` supersedes the theme's `converted` on the same journey; `shipped` and `canceled` are usually additions.

On approval, work through the target campaign's journey socket:

* Duplicate each partner business event into the socket holding the program's equivalent, sourcing from the integration's component.
* Remove the superseded default event once its replacement is installed.
* Add the partner events the program lacks into the same socket.
* Read the built campaign and confirm the journey lists the expected events in lifecycle order.

Record which events were replaced, which were added, and what the journey contains afterwards.

## Reference Structure for an Order Lifecycle Integration

Most commerce platforms map onto the same three canonical events; adjust this shape to what the partner emits:

| Canonical event | Reusable template                    | Partner input event                                              |
| :-------------- | :----------------------------------- | :--------------------------------------------------------------- |
| `converted`     | `template_transacted_business_event` | Order created or order qualified                                 |
| `shipped`       | `template_tracked_business_event`    | Shipment                                                         |
| `canceled`      | `template_tracked_business_event`    | Cancellation, plus any legacy spelling a live sender still emits |

[Map Partner Events to Business Events](/technical/building-partner-integrations/integration-types/partner-events-map-to-business-events) names the fields each event captures. A complete integration of this shape carries the model component, three business events, one `input_event` rule per event, one data component per captured field, and the three baseline views. It is Partner to Extole only: no reward-supplier socket, reward webhook, or client key.

Platforms with a different lifecycle keep the same construction and change the event set: a lending or account platform maps to `account_opened`, `application_approved`, and `funded`; a subscription platform to `converted`, `renewed`, and `canceled`. The canonical name describes the business outcome, never the partner's transport name.

## Related Documentation

* [Build a Partner Integration with the Management API](/technical/building-partner-integrations/integration-lifecycle/management-api-integration)
