> ## 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.

# Build a Partner Integration with the Management API

> Build a partner platform into a reusable Extole integration through the Management API, with the Extole AI tools as the recommended build path.

# Overview

A partner integration is a campaign whose component tree connects Extole to an outside platform, assembled from reusable component types so the same build can be installed and configured in any account. The [Management API](/technical/platform-integrations/rest-apis/index) builds that campaign and its components directly in a client account.

The model is the same whether or not the finished build is published for other accounts to install:

* **Reusable component types**, not one-off controllers.
* **Typed sockets** — attachment points that accept only components of a declared type, such as a `views` socket holding view components.
* **Business-event templates** — maintained components that produce a canonical Extole event such as `converted` or `shipped`.
* **v10 component types**, named with the generation as a suffix: `integration-v10.1`, `config-view-v10.0`.
* The naming conventions and validation rules the integration passes before publication.

Examples use a generic partner named `example`. Substitute the real partner name, event names, and field names.

## Who Builds a Partner Integration

Building one is platform engineering on a reusable artifact — a partner connector meant to be installed repeatedly and maintained over time. It is not a step in launching a program, and most clients never do it. Extole solutions engineers, partner engineering teams, and clients building a connector for a platform Extole does not yet maintain are the audience for this guide.

If you are connecting your own systems to Extole, one of these is your path instead:

| You want                                                   | Go to                                                                                                                                 |
| :--------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------ |
| To connect your site, app, or servers and launch a program | [Integrating with Extole](/technical/integration-overview/integrating-with-extole) — the JavaScript SDK, REST APIs, and mobile SDKs   |
| To connect a platform Extole already maintains             | Install it from the My Extole [Integrations page](https://my.extole.com/integrations); there is nothing to build                      |
| To send your own platform's events server-side             | [Send Events from the Partner Platform](/technical/building-partner-integrations/integration-types/partner-events-send-from-platform) |
| To send records as CSV or SFTP files                       | The [File Integration](/technical/platform-integrations/extensions/file-integration) extension                                        |

Even when this is your job, confirm Extole does not already maintain a source for the partner before you build anything — [When You Would Build One](#when-you-would-build-one) starts there.

## Build with Extole AI Tools

The recommended path is to run the build through the [Extole MCP server](/technical/extole-ai-tools/extole-mcp-server/index) from an agentic coding tool — [Claude Code](/technical/extole-ai-tools/extole-mcp-server/setup-claude-code), [Cursor](/technical/extole-ai-tools/extole-mcp-server/setup-cursor), or [Codex](/technical/extole-ai-tools/extole-mcp-server/setup-codex) — with the [Extole CLI](/technical/extole-ai-tools/extole-cli/index) alongside it. Point the tool at this guide and the partner's page, and describe the integration you need.

The build suits an agent better than it suits a person:

* It is dozens of component duplications in a required order, each needing a fresh campaign version, and one stale value rejects the call.
* Maintained components resolve **by name** at build time, so every duplication starts with a lookup whose result is used once and never stored.
* Verification uses the same tool surface as the build: read the component tree back, send a test event, read the resulting steps.
* Changes execute under your own Extole permissions and are attributed to you in the change log, exactly as they are through My Extole or the API.

The `curl` examples throughout this guide are the underlying contract. Read them to understand what a tool did, to check a finished build, or to work through the sequence by hand.

## When You Would Build One

| You want                                                                                                             | Category                                  | Start at                                                                                                                                          |
| :------------------------------------------------------------------------------------------------------------------- | :---------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ |
| A client's commerce, banking, or subscription platform to send purchases, shipments, or account activity into Extole | Partner to Extole                         | [Sending Partner Events to Extole](/technical/building-partner-integrations/integration-types/partner-events-to-extole)                           |
| Extole activity to reach a marketing automation, messaging, analytics, or customer data platform                     | Extole to Partner                         | [Build an Extole to Partner Integration](/technical/building-partner-integrations/integration-types/integration-build-extole-to-partner)          |
| Extole to order gift cards, prepaid cards, points, or payouts when a participant earns a reward                      | Reward fulfillment                        | [Build a Reward Fulfillment Integration](/technical/building-partner-integrations/integration-types/integration-build-reward-fulfillment)         |
| A partner's own webhook, whose payload you do not control, to produce Extole events                                  | Partner to Extole, with a prehandler      | [Normalize Partner Events with a Prehandler](/technical/building-partner-integrations/integration-types/partner-events-prehandlers)               |
| A platform to decide who is eligible and send that membership to Extole, rather than reporting events                | Partner to Extole, as audience membership | [Receive Audience Membership from a Partner](/technical/building-partner-integrations/integration-types/partner-events-audience-membership)       |
| To inspect, configure, or test the component model in a development account                                          | Any                                       | [Create the Integration Campaign and Component Model](/technical/building-partner-integrations/integration-lifecycle/integration-component-model) |

[Integration Categories](/technical/building-partner-integrations/integration-types/integration-categories) describes what each category contains. A partner that both sends outcomes and receives rewards uses two paths: build the Partner to Extole half first, then add the Extole to Partner resources. Adding Partner to Extole scope to a maintained Extole to Partner install works the same way — install the maintained source, then add the incoming half to the installed campaign, business events for a partner that reports activity or an audience and credential for one that sends eligibility. Check the finished integration against every category the request matched.

Check for a maintained source before building anything. Query the duplicatable listing for an integration component whose **name** matches the partner, not a fixed type version — a source may be typed `integration-v10.0`, `integration-v10.1`, or later, and a query pinned to one revision reports a maintained partner as missing. Rebuilding a maintained partner from `custom_integration` produces a campaign that does none of the partner's webhook or credential work.

When this documentation set has a page for your partner, read it first. It carries that platform's wire contract — event names, payload fields, status mapping. Partner pages use the partner's name as the page slug.

### Client-Local Build or Registered Integration

Building the tree in one account does not register the partner for anyone else.

| Outcome                                          | What to do                                                                                                  |
| :----------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |
| An integration this client uses                  | Duplicate the maintained source, or build the campaign and component tree.                                  |
| An integration every client can find and install | Build and validate in a development account, then publish the reusable component as an Extole-owned source. |

The My Extole [Integrations page](https://my.extole.com/integrations) lists components tagged `internal:type:integration`. It treats one as installed when its source client is this client, and as available to install when the source client is Extole. Two conditions decide whether a client-owned component appears at all:

* The integration component must be a **child of the campaign root**. Root components are excluded.
* Without **`internal:self-managed`** the entry renders as unavailable.

<Note>
  `internal:integration-component-name:<component-name>` is an older convention that published integration bundles carry for traceability. The Integrations page does not read it, so it neither reveals nor hides a build. When an integration is missing from the page, check the component's tags, its owner, and whether it is the root.
</Note>

## Before You Start

| Source                                                       | Values                                                                                                                                                                                                                   |
| :----------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The partner page, then the partner's developer documentation | Platform and version, category, event names and payload fields, identity and deduplication fields, status mapping, the settings the integration exposes, and any partner destination, authentication, and retry contract |
| Derived from the partner name                                | Campaign name, a stable lowercase component name, and a unique program label                                                                                                                                             |
| Your Extole account                                          | A server-side access token from the [Security Center](https://my.extole.com/security-center) authorized to manage campaigns and components and to read people, and the client that token authenticates to                |
| Nowhere — request these                                      | The partner's API secret, any account identifier the partner issues, and the logo artwork                                                                                                                                |

Confirm the target client before the first write. A token pointed at the wrong account builds a live integration there.

The last row does not block the build. Build everything that does not depend on those three values and track them as outstanding.

### One Host, Two Access Tokens

Management calls and event submission both go to `api.extole.io`. Examples read it from `EXTOLE_API_HOST`:

```bash theme={null}
EXTOLE_API_HOST=https://api.extole.io
```

Use separate access tokens for the two. The partner application receives only the token that can submit events, never the one that can manage campaigns and components.

## How to Build

Work through the pages in order. Each build sequence is a page of its own:

| Page                                                                                                                                              | Covers                                                                                                                            | Needed for                                                               |
| :------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------- |
| [Create the Integration Campaign and Component Model](/technical/building-partner-integrations/integration-lifecycle/integration-component-model) | The campaign, root, and integration component; display metadata and logo; typed sockets and the configuration view                | Every path                                                               |
| [Add the Activity and Event Views](/technical/building-partner-integrations/integration-lifecycle/integration-activity-views)                     | The report-runner and event-stream views, the report runner and event stream behind them, and the republish each attachment needs | Every path                                                               |
| [Send Events from the Partner Platform](/technical/building-partner-integrations/integration-types/partner-events-send-from-platform)             | The sending code that runs in the partner platform                                                                                | Partner to Extole, when you control the sender                           |
| [Normalize Partner Events with a Prehandler](/technical/building-partner-integrations/integration-types/partner-events-prehandlers)               | Reshaping a partner's own webhook at ingest                                                                                       | Partner to Extole, when the partner defines the payload                  |
| [Map Partner Events to Business Events](/technical/building-partner-integrations/integration-types/partner-events-map-to-business-events)         | Business events, input event rules, and event data                                                                                | Partner to Extole                                                        |
| [Receive Audience Membership from a Partner](/technical/building-partner-integrations/integration-types/partner-events-audience-membership)       | The audience, the credential the partner authenticates with, and the setup instructions naming the membership endpoints           | Partner to Extole, when the partner sends eligibility rather than events |
| [Build an Extole to Partner Integration](/technical/building-partner-integrations/integration-types/integration-build-extole-to-partner)          | Installing a maintained source, reshaping it, and attaching webhooks and a credential                                             | Extole to Partner                                                        |
| [Build a Reward Fulfillment Integration](/technical/building-partner-integrations/integration-types/integration-build-reward-fulfillment)         | Supplier type, support campaign, supplier templates, and `REWARD` webhooks                                                        | Reward fulfillment                                                       |
| [Validate and Publish an Integration](/technical/building-partner-integrations/integration-lifecycle/integration-validation)                      | Gating Extole to Partner resources, the validation checklist, and connecting the integration to a program                         | Every path                                                               |

A campaign and an integration component alone are the container. The events, views, and webhooks are the integration.

### Refresh the Campaign Version Between Mutations

Every campaign mutation creates a new version, and version-scoped endpoints reject a stale one. Read the version immediately before each mutation:

```bash theme={null}
CAMPAIGN_VERSION=$(
  curl --silent --show-error --fail-with-body \
    "$EXTOLE_API_HOST/v2/campaigns/$CAMPAIGN_ID" \
    --header "Authorization: Bearer $MANAGEMENT_API_ACCESS_TOKEN" |
  jq --raw-output '.version'
)
```

The path segment is singular — `/version/{version}`, not `/versions/`:

```text theme={null}
/v2/campaigns/{campaign_id}/version/{version}/components
```

On `stale_version` or `concurrent_update`, retrieve the campaign, reconcile, and retry only the intended mutation.

### Find Reusable Components

`GET /v1/components/duplicatable` returns the components this client can duplicate, including those available through subscriptions and grants:

```bash theme={null}
curl --get "$EXTOLE_API_HOST/v1/components/duplicatable" \
  --header "Authorization: Bearer $MANAGEMENT_API_ACCESS_TOKEN" \
  --data-urlencode "name=template_transacted_business_event" \
  --data-urlencode "version_state=PUBLISHED" \
  --data-urlencode "having_any_types=business-event-v10.0" \
  --data-urlencode "show_all=true"
```

| Component                            | Program label     | Purpose                                       |
| :----------------------------------- | :---------------- | :-------------------------------------------- |
| `template_transacted_business_event` | `business-events` | Revenue or transaction outcome                |
| `template_tracked_business_event`    | `business-events` | Non-revenue lifecycle milestone               |
| `input_event`                        | `rules`           | Matches one or more partner input event names |
| `business_event_data`                | `business-events` | Captures one mapped field                     |
| `event_id`                           | `business-events` | Captures the Extole event identifier          |

Once the target component and socket exist, add `target_component_id` and `target_setting_name` to return only socket-compatible components. `target_socket_name` is deprecated. Narrowing this way matters because a widely used source such as `input_event` appears once for every campaign that installed a copy of it — those duplicates are copies of one maintained source, not alternative behaviors.

Check each candidate's type before duplicating, and prefer v10 when a legacy version shares the name.

### Constraints

These hold on every path:

* **Resolve maintained components by name at build time.** Stored identifiers go stale without failing loudly.
* **Use the reusable business-event, rule, and data components.** Write a custom controller only where no template implements the behavior.
* **Carry all three baseline views** — configuration, report-runner, and event-stream. The category decides what the report counts and what the feed filters to, not whether the tabs exist. Reward fulfillment adds a fourth, a `reward-suppliers` configuration view.
* **Create reward suppliers, client keys, and webhooks only for an Extole to Partner flow the integration has.** A Partner to Extole integration needs none.
* **Keep partner event names and canonical Extole names separate.** The trigger rule carries the wire name; the business event carries `converted`, `shipped`, or another canonical name. Renaming a business event to match a partner breaks every program and report reading the canonical name.
* **Map every field you persist**, in the same pass that creates the business events. A business event with an empty `data` socket cannot deduplicate, attribute, reward, or report.
* **Assign key types by meaning, not spelling.** A partner field named `customer_id` may hold the partner's own identifier rather than an Extole person key.
* **Keep secrets in a webhook client key or protected setting** — never in component descriptions, logs, or example payloads.

Reusing an active integration whose campaign and component identity already match is preferable to building a second one. Archived campaigns are not candidates: they receive no events, and an archived campaign holds no program label against a new one, so its label is free to reuse.

## How to Test

Test every arriving event and every configured partner destination before you call the integration live.

**Partner to Extole.** Send a synchronous event to `POST /v6/events` with the current program label in `data.labels`, then read the step it produced:

```bash theme={null}
curl --get "$EXTOLE_API_HOST/v5/persons/$PERSON_ID/steps" \
  --header "Authorization: Bearer $MANAGEMENT_API_ACCESS_TOKEN" \
  --data-urlencode "campaign_ids=$CAMPAIGN_ID" \
  --data-urlencode "names=converted"
```

Confirm the step carries the canonical event name, that the transaction identifier and value match the source record, that person keys resolve, and that resending the same source identifier produces a duplicate outcome rather than a second conversion. Repeat for every event the integration accepts. [Send Events from the Partner Platform](/technical/building-partner-integrations/integration-types/partner-events-send-from-platform) covers the sending side and what to check when Extole accepts an event but no business event appears.

**Extole to Partner.** Trigger the Extole event the integration forwards and confirm the webhook fired against the partner endpoint.

**The component tree.** Read the campaign and its built components back. Confirm every typed child carries its type, each webhook exists with its tags and resolved URL, and each `WEBHOOK_ID` setting resolves to a webhook identifier.

A successful publish validates the model, not the behavior. Prehandler scripts and a data component's `valueExpression` are stored without ever being executed, so only a real payload proves they run. [Validate and Publish an Integration](/technical/building-partner-integrations/integration-lifecycle/integration-validation) covers the full gate.

The integration is not live while the campaign is in draft, a webhook is disabled, a URL is a placeholder, or an event is untested.

### What to Record

Keep these identifiers as you build, for verification and for cleaning up test data:

* Client and environment.
* Campaign identifier, version, state, and program label.
* Root and integration component identifiers.
* Canonical business events and the partner trigger names that reach them.
* Field mappings and key types.
* View components, and the report runner and event stream each resolves to.
* External resources created, or confirmation the category needed none.
* Programs whose business events changed, or confirmation the integration is not yet connected to one.
* Test event identifiers and results.
* Partner-side steps that remain.

## Related Documentation

* [Integration Categories](/technical/building-partner-integrations/integration-types/integration-categories)
* [Sending Partner Events to Extole](/technical/building-partner-integrations/integration-types/partner-events-to-extole)
* [Integrating with Extole](/technical/integration-overview/integrating-with-extole)
