What the Inbound Custom Workflow Creates
A complete inbound custom integration contains:input_event
An inbound build carries the same three views as every other category. The configuration view comes from Create the Integration Campaign and Component Model; the other two, and the report runner and event stream they resolve to, come from Add the Activity and Event Views. Chart and stream the canonical business events this integration produces.
The partner event name belongs in an input_event trigger rule. The canonical Extole event name belongs on the reusable business-event component. Do not rename the Extole business event to match the partner wire event.
This tree receives events; it does not produce them. The extension, service, or feed that sends them from the partner platform is built against Send Platform Events to Extole, and an inbound integration is finished only when both halves exist.
Settle Who Shapes the Payload First
Everything on this page assumes the event arrives with a name inevent_name and its fields readable in data. That assumption holds when the sender is built for this integration — an extension, a plugin, or a service written against Send Platform Events to Extole — because whoever writes it can shape what it sends.
It does not hold when the sender is the partner’s own webhook. A partner defines its payload for its own purposes: the event type sits in a body field rather than in event_name, and the interesting values sit two or three levels down. Such a webhook still reaches Extole — the named form of the Events API takes the event name from the URL and accepts any body — but what arrives is the partner’s shape, not the shape this page assumes.
Reconcile that inside Extole with a prehandler, which renames the event and flattens the payload before any rule on this page sees it. Normalize Inbound Events with a Prehandler covers the endpoint to give the partner, the decision, and the build. Two things on this page change when one is in play: the input_event rule lists the name the prehandler produces rather than the partner’s wire name — an integration-owned name such as example_order_completed, never the canonical outcome name the business event itself carries — and each data component’s valueExpression reads the flattened field rather than the partner’s nesting.
The alternative — instructing the customer to build and host a service that receives the partner’s webhook and re-posts it in Extole’s shape — is a customer engineering project, and one this guide does not describe. Choose it deliberately or not at all.
Add Reusable Business Events
Choose the template by business meaning:- Use
template_transacted_business_eventwhen the event carries transaction value or represents the program outcome. - Use
template_tracked_business_eventfor lifecycle milestones without transaction value.
businessEvents socket:
event_name
Use the canonical v10 name that matches the business outcome. Examples include converted, shipped, canceled, returned, account_opened, and application_approved. Do not use a transport-specific name such as partner_order_created as the business-event component name.
Let the partner’s events decide how many you create. Enumerate the wire events in scope, decide which outcome each one represents, and create a business event for every distinct outcome — then give each the canonical name that fits it. Do not create duplicate legacy controllers alongside the reusable component.
Enumerating in the other direction is the mistake that survives: pick the canonical names first and the wire events get fitted into whichever of them is nearest. A failed authorization and a refunded charge are both tempting to call canceled, and an integration that calls them both that has no way to distinguish a payment that never completed from money that was taken and given back — not in a report, not in a rule, not in a clawback. returned is on the list above for exactly that outcome. Two wire events share one business event only when they are genuinely the same thing happening twice, and the test is whether anyone would ever need them apart.
Count the events you created against the wire events in scope before calling this stage done. Three wire events and two business events is either a deliberate merge you can name, or an outcome that quietly lost its own identity.
Set sequence so the events sort in lifecycle order, with the outcome event first and later milestones after it. The value orders steps within the funnel; the exact numbers matter only relative to one another.
Set the reporting names on every duplicate. singularNounName, pluralNounName, and rateName are what reports and the admin funnel display. The templates ship with generic values — a tracked template calls everything “Tracked Events” with a “Tracked Event Rate”, and singularNounName defaults to an expression that echoes the display name — so two events duplicated from the same template report under identical labels until you override them. Give each canonical event its own noun and rate names, and give each an adminUIIcon that reads as its outcome. No two events in one integration should share an icon.
Set aliases to the alias set the platform already uses for that canonical event. Aliases are additional names that this business event matches, and platform consumers subscribe to them: an extension or downstream integration listening for outcome sees a converted event only because converted carries that alias. Read the alias set from an existing program’s business event of the same name rather than inventing one. Bundled programs use these:
Do not add partner-flavored aliases, and do not clear an alias set the template or canonical event provides. The same alias must never appear on two business events in one campaign: the match becomes ambiguous, and the event that wins is not something the configuration expresses.
Inspect the duplicated component’s evaluated
journeyName and roleName values. Do not hardcode one pair for every integration: these values depend on whether the event is associated with a campaign journey and on the surrounding role and journey hierarchy. Preserve the reusable template’s defaults unless the integration contract requires different values, and record the published values during verification.
Configure Input Event Rules
Duplicateinput_event from the rules program into each business event’s triggerRules socket:
data
Keep the duplicated rule under its source name input_event. Library components and bundled programs all do, so a reader recognizes the trigger by its position in the business event rather than by a component name that restates the event it listens for. The partner event name belongs in triggerEventNames.
When a prehandler renames the event, triggerEventNames lists the name the prehandler produces, not the name the partner sent. Prehandlers run before trigger rules, so a rule still listening for the wire name never matches — and it reads as correct in the component tree, which is why this is worth checking rather than assuming.
Add a legacy partner event alias only when a real sender still emits it. Document the preferred spelling and migration plan.
Configure Event Data
Data capture is the part of the integration that carries meaning. Without it an inbound event produces a step with no transaction identifier, no person key, and no value, so nothing downstream can deduplicate, attribute, reward, or report on it. Create the data components in the same run as the business events they belong to. An integration whosedata sockets are empty is not built, however complete its tree looks.
Take the field names from the partner’s documented payload. When a partner-specific page exists in this documentation set, its payload example is the contract; otherwise use the partner’s own developer documentation. Ask the requester for a sample payload only when neither source defines the field, and create the identity and deduplication fields that are defined rather than deferring the whole mapping.
Define a mapping before creating data components:
Duplicate one
business_event_data component into the business event’s data socket for each field:
event_name
Set valueExpression explicitly when the partner field and Extole field have distinct names. Verify the expression against a real sanitized partner payload. Do not rely on the data component’s name-derived default when the source field differs.
Quote the key with escaped double quotes, as above. A single-quoted --data payload cannot contain single quotes: the shell closes the string at the first one, so getData()['order_id'] reaches the API as getData()[order_id], which reads an undefined variable instead of the partner field and silently captures nothing.
Use NO_ADDITIONAL_DATA when the event must store only declared fields. Capture the minimum data needed for identity, deduplication, attribution, rules, and reporting.
Every business event needs its own data components — a field captured on one event is not visible on another. What each event must capture follows the table above rather than one fixed set:
- Enough identity to resolve a person, on every event. Capture the partner customer identifier as
PARTNER_PROFILE_KEYwhenever the partner sends a stable one, andemailwhen it is the only identity available. - The transaction identifier as
UNIQUE_PARTNER_EVENT_KEY, on transaction events. An event tied to an order, a purchase, or another partner-side record needs it to deduplicate. A standalone lifecycle event such asaccount_openedhas no transaction to key on, and requiring one there invents a field the partner does not send. - The amount as
VALUE, on revenue events.
shipped and canceled: they arrive independently and must resolve to the same person and, through the transaction identifier they carry, the same original transaction.
Verify Inbound Events
Send a synchronous test event throughPOST /v6/events. Event submission uses the same host as the management calls above but a different access token, so a caller that can create campaigns is not necessarily able to submit events. When the calling context has no event-submission token, hand the request below to whoever does, together with the values the resulting step must contain, and report the integration as built but unverified.
Put the current program label inside data to target this campaign during the test. The label is a testing convenience and does not belong in the partner’s own payload or setup instructions.
input_event
Use the returned person_id to list the person’s resulting events:
example_order_completed
Confirm the canonical event name and every mapped value. Use a new unique identifier for each repeat test unless duplicate handling is the behavior under test.
Test:
- Every preferred partner input event.
- Every supported legacy alias.
- Missing required identity.
- A repeated unique partner event identifier.
- Invalid amount and status values.
- Partner retry behavior.
- Campaign targeting with the current program label.
- Configuration view contents and status.
