Overview
An Extole to Partner integration forwards Extole program activity to a partner platform. Start from a maintained source when it includes the required controllers and webhooks. When the source contains only display metadata, add the controller-backed delivery yourself. Substitute the component name, endpoints, and tag namespace from the partner page throughout. Build a Partner Integration with the Management API covers the constraints and shared mechanics every build follows.When You Would Build One
Do not add Partner to Extole business-event scaffolding to this install. A partner that orders gift cards, prepaid cards, points, or payouts uses the distinct reward fulfillment model.
Before You Start
Read the partner page first — it names the finished tree, the endpoints, and the tag namespace — and inspect any matching source before choosing the build path. Without a complete source, create the container from Create the Integration Campaign and Component Model, then add the controller-backed delivery described below.
Choose the Build Path
List the duplicatable sources whose name matches the partner exactly, accepting everyintegration-v10.* revision — Install the Maintained Source shows the query — then inspect the integration component and its children.
The integration component’s integration-v10.* type tells you the version, not whether the source delivers anything. A complete maintained source has all of the following:
- An integration component tagged
internal:self-managed - Child controllers for the activity it forwards
- Webhook actions with event-specific data
- The webhooks and credential settings those actions reference
Share-link creation and
shared are distinct. The first creates a shareable and exposes its link; the second records a share action.
Forwarding a fulfilled reward to a messaging or analytics partner is not the same as a partner that supplies the reward. A gift card, prepaid card, points, or payout provider uses Build a Reward Fulfillment Integration.
How to Build
Confirm the Finished Shape
The partner page’s product description specifies the finished tree. Each statement it makes maps to something the install must carry:
Read that mapping as exhaustive rather than as a minimum, and apply it to an integration already in the account as much as to a fresh install. A maintained source ships the union of what every account might want, so it commonly installs children the page does not list and only one of the webhooks it names.
A maintained source may not ship the report-runner and event-stream views every integration carries. Read the installed
views socket and add whichever is missing from Add the Activity and Event Views.
Create Controller-Backed Outbound Delivery
Skip this section when the maintained source already contains the requested controllers and payloads. Create one controller per event class or payload contract. Attach the controller to the integration component withcomponent_ids; do not modify a marketing campaign to host integration behavior.
Create a controller:
CONTROLLER_ID.
Refresh the campaign version, then add a step-event trigger:
event_type set to SHAREABLE and read the link from context.causeEvent.shareable.link.
Create every controller and trigger while the path is disabled. Then publish and create the component-scoped webhook, as described in Publish, Then Attach Component-Scoped Webhooks, and attach it to the controller through Attach the Webhook Action. Take field names and identity rules from the partner page.
Create Missing Component Types
A typed child needs its component type first, and a partner page can require a type the account has never used. Read the type, and create it only when the read finds nothing:parent. An empty types array leaves an untyped component, which satisfies no socket filter and no template lookup.
Install the Maintained Source
An install isPOST /v1/components/{SOURCE_COMPONENT_ID}/duplicate without target_campaign_id: omitting the target campaign creates a new root integration campaign that copies the source tree, including its webhooks and child controllers. Send a body carrying at least one property, such as component_display_name.
List the candidates before duplicating anything:
Reshape the Install
The reshape uses these calls, each needing a campaign version read immediately beforehand:
Bring the installed tree to the partner page’s shape in one pass:
- Delete the installed children the partner page does not keep.
- Create the children it adds, including any typed data template.
- Remove parent settings that belonged to a deleted child, such as a trigger-event-name setting whose controller is gone.
- Set one
WEBHOOK_IDsetting per partner endpoint, resolved by webhook tag rather than by identifier, so the setting survives a rebuild:
internal:partner:message-trigger, matching the webhook below. Never use a shared tag such as internal:partner, which matches every webhook the integration owns.
A partner data template is a typed child of the integration component, created through component_ids with no socket. Its install expression anchors the source component’s unanchored step data onto the target event:
Publish, Then Attach Component-Scoped Webhooks
Publish the campaign once before creating any webhook whose name or URL expression callscontext.getComponent(), and create those webhooks with component_ids naming the integration component. The reshape cannot complete without that publish, so get any release approval first.
Publishing validates every webhook the campaign already owns, so keep a valid placeholder host in any account-URL setting that feeds a webhook URL. The maintained source’s own default is one. Set enabled to false while a webhook points at that placeholder — enabled, it sends live program data to a host that should never receive it, unsigned when the client key is also missing. Enabling it is the step that puts the partner connection into service.
POST /v6/webhooks:
WEBHOOK_ID.
Name each webhook for the endpoint it calls: an ingestion endpoint and a message-trigger endpoint are separate webhooks with separate tags. Keep the broad internal:partner tag for listing every webhook the integration owns. Where the account URL setting may lack a scheme, build the URL expression to add https://.
Attach the Webhook Action
Refresh the campaign version after creating the webhook, then attach the action to its controller. Map the complete partner payload here rather than leaving a generic request body for later:Complete the Request and Response Handlers
The default request handler serializes the webhook action’s data as a JSON body, uses the configured method and URL, and applies the client key’s default authentication. APASSWORD key adds an Authorization: Bearer header.
Write a custom request expression when the partner requires a distinct authentication header, body envelope, URL, method, or idempotency key. Build the request from the webhook action data and the client key, following the contract on the partner page. Do not use createRequestBuilderWithDefaults() when its default authentication differs from the partner’s requirement.
The response handler returns:
OKwhen processing is completeRETRYwhen Extole should use the configured retry intervals
429 or 5xx from terminal 4xx configuration or payload errors. Log the terminal status and the minimum response detail needed to diagnose the rejection; do not log credentials or the full participant payload.
A webhook is ready when its request handler produces the partner’s required body and authentication and its response handler follows the partner’s retry contract. Keep it disabled until both are verified.
Attach the Credential
Create the webhook client key once you have the partner’s API secret, then set the credential setting on the integration component. A missing credential does not block the build: leave the setting null and track it as outstanding.Error Handling
How to Test
A2xx on the duplicate call means the source tree was copied, not that the install matches the partner page. Read the campaign and its /v6/webhooks entries back, then confirm:
- The tree matches the partner page: one child per activity the page lists, and no child forwarding activity it does not.
- Every typed child carries its type.
- Every requested activity has the matching controller trigger:
SHAREABLE,STEP, or aFULFILLEDreward event. - Every controller has a webhook action with the complete partner payload.
- Each webhook exists with its tags and its resolved URL.
- Each
WEBHOOK_IDsetting resolves to a webhook identifier rather thannull. - Request and response handlers match the partner’s authentication, body, success, and retry contracts.
enabledistrueon every webhook whose real URL and credential are both configured, andfalseon the rest.
