en
Salesforce Campaigns with OpenAPI

Salesforce Campaigns ↔ Alvio

Alvio provides an OpenAPI 3.0 contract (opens in a new tab) for two Salesforce External Services actions:

ActionAlvio operationPurpose
sendCampaignContactPOST /api/campaigns/webhook-receiver?campaign_id=...Add or update a campaign contact.
listCampaignContactResultsGET /api/campaigns/{campaign_id}/contact-resultsRead contact, sequence, and latest message delivery states.

These actions use one x-api-key token per Alvio campaign. The token is issued when you create the campaign's API/webhook source. The OpenAPI document describes the header for other clients; Salesforce External Services ignores OpenAPI security schemes, so configure the header on a Salesforce Named Credential.

1. Prepare Alvio

  1. Create an Alvio campaign and enable its API/webhook source.
  2. Save the campaign UUID and the x-api-key token displayed once. Keep the key in Salesforce credentials, not in a Flow variable.
  3. Start with a draft campaign and a test Lead or Contact. An active single-message campaign with an approved template can send immediately; an active sequence runs asynchronously.

Use a separate Named Credential and External Services registration for each Alvio campaign because each has a different token.

2. Register Salesforce External Services

  1. In Salesforce Setup, create an External Credential using Custom authentication and a Named Principal. Add an authentication parameter containing the Alvio campaign key and grant its principal access through a permission set.
  2. Create a Named Credential with URL https://www.alvio.ai using that External Credential. Add a custom header named exactly x-api-key, whose value references the authentication parameter.
  3. Under External Services, register a service from the OpenAPI JSON file (opens in a new tab). Select the Named Credential and import sendCampaignContact and listCampaignContactResults.

Salesforce's Named Credential guide (opens in a new tab) explains how External Services combines its URL with an OpenAPI 3.0 server path. Its HTTP callout authentication guide (opens in a new tab) shows the custom header setup. The OpenAPI file uses a literal https://www.alvio.ai server URL for import compatibility.

3. Send Campaign Members

In an after-save record-triggered Flow on CampaignMember, put the sendCampaignContact action on the asynchronous path. Salesforce does not allow an external callout on the synchronous record-save path. Select members with a usable phone number and the required contact permissions. Map fields as follows:

Salesforce valueAlvio input
Alvio campaign UUID for this Flowcampaign_id query parameter
Lead or Contact phonephone_number (prefer E.164)
Lead or Contact namecontact_name
Lead or Contact emailcontact_email
Lead ID or Contact IDcrm_contact_id
Campaign IDsalesforce_campaign_id
CampaignMember IDsalesforce_campaign_member_id

The Lead or Contact ID is used with the phone number as Alvio's repeat-delivery identity for this campaign. Call sendCampaignContact once for each selected member. Check the response's errors and skipped values even when the HTTP status is 200; success: true alone does not confirm every contact was processed. See Salesforce's record-triggered Flow considerations (opens in a new tab) for the asynchronous path.

4. Follow results back into Salesforce

Run a schedule-triggered Flow for each Alvio campaign that calls listCampaignContactResults with the same campaign UUID and credential. Salesforce permits External Services callouts without a Wait element in a scheduled Flow that processes a batch of records on API version 63.0 or later; otherwise add a Wait element before the callout. See Salesforce's schedule-triggered Flow considerations (opens in a new tab). Start with offset=0, limit=100; repeat with next_offset until it is null. On every scheduled run, start again at 0 because existing results can change. Make the callouts before updating CampaignMembers in a transaction. For large campaigns, spread the pages across transactions to stay within Salesforce callout limits.

Use salesforce_campaign_member_id to match each result to its CampaignMember. delivery_status is the state of the most recent campaign message (queued, sent, delivered, read, replied, failed, unknown, or null). contact_status, sequence_status, and progress_status show campaign execution separately. Map those values to the CampaignMember statuses configured in your Salesforce org. For example, replied can map to your responded status, while failed can drive an error task or a dedicated status.

The result endpoint returns a snapshot, so it is suitable for scheduled reconciliation. It does not create a Salesforce webhook or push updates automatically. If a result has no salesforce_campaign_member_id, match it using crm_contact_id and the Alvio campaign ID, or review it manually.

Direct API test

curl -X POST 'https://www.alvio.ai/api/campaigns/webhook-receiver?campaign_id=<ALVIO_CAMPAIGN_ID>' \
  -H 'Content-Type: application/json' \
  -H 'x-api-key: <CAMPAIGN_API_KEY>' \
  -d '{"phone_number":"+33612345678","crm_contact_id":"00Q000000000001","salesforce_campaign_member_id":"00v000000000001"}'
 
curl 'https://www.alvio.ai/api/campaigns/<ALVIO_CAMPAIGN_ID>/contact-results?limit=100&offset=0' \
  -H 'x-api-key: <CAMPAIGN_API_KEY>'

See the webhook integration guide for the generated Hookdeck URL and general payloads.