CXone Personal Connection API outbound call 400 Bad Request

Does anyone know the exact payload structure for triggering an outbound call via the CXone Personal Connection API? I am sending a POST to /api/v2/outbound/campaigns/{id}/executions with a valid auth token, but I keep getting a 400 Bad Request. My JSON includes the contactId and contactSpec, yet the error message is generic.

Here is the snippet. The documentation is vague on required nested fields for contactSpec.

import requests
headers = {'Authorization': 'Bearer <token>', 'Content-Type': 'application/json'}
payload = {
 'contactId': '12345',
 'contactSpec': {
 'address': '+1234567890',
 'type': 'voice'
 }
}
requests.post(url, headers=headers, json=payload)

The logs show no specific validation failure. Am I missing a required attribute in contactSpec?

The root cause here is the mismatch between the contactSpec structure for the v2 Outbound Campaign execution API and the Personal Connection trigger. The endpoint /api/v2/outbound/campaigns/{id}/executions expects a specific schema including contactId, a contactSpec with contactId and contactData, and potentially campaignId if not in the path. However, for Personal Connection, you should not use the campaign execution endpoint directly. You need to use the Personal Connection specific endpoint or ensure the campaign is configured for manual triggers.

If you’re trying to trigger a Personal Connection via API, you likely need to use /api/v2/outbound/contacts/{contactId}/personal-connections or verify the contactSpec contains the required contactId and contactData fields with the correct media type. Here’s a payload structure for a standard outbound execution if you’re stuck on that path, but note Personal Connections often require a different approach.

import requests

headers = {
 'Authorization': f'Bearer {token}',
 'Content-Type': 'application/json'
}

payload = {
 "contactId": "1234567890abcdef1234567890abcdef",
 "contactSpec": {
 "contactId": "1234567890abcdef1234567890abcdef",
 "contactData": {
 "phoneNumber": "+1234567890"
 }
 }
}

response = requests.post(
 f'https://api.cxone.net/api/v2/outbound/campaigns/{campaign_id}/executions',
 headers=headers,
 json=payload
)
print(response.status_code)
print(response.text)
  • Verify campaign allows manual execution.
  • Check the contactData schema matches your media type.
  • Ensure your OAuth scope includes the necessary permissions for outbound execution.
  • Confirm the contact exists within the appropriate contact list associated with the campaign.
1 Like

The simplest way to resolve this is to bypass the campaign execution endpoint entirely. Personal Connection triggers require a distinct payload structure that the standard outbound API does not accept.

Use the specific Personal Connection trigger endpoint instead. Send a POST request with the contact ID and reason code in the body to initiate the engagement.

Check the response headers for the engagement ID. This approach avoids the schema mismatch causing your 400 errors and provides direct tracking for sentiment analysis pipelines.

1 Like

This is typically caused by using the campaign execution endpoint instead of the Personal Connection trigger API. Schema validation fails because the fields don’t align with that path.

The correct endpoint is /api/v2/outbound/personal-connections. This route expects a simpler payload for ad-hoc outreach, not scheduled campaigns.

Use this curl example to verify your payload. Ensure your token has the outbound:personal-connection:initiate permission. The response will return the engagement ID on success.

curl -X POST "https://api.cxone.net/api/v2/outbound/personal-connections" \
 -H "Authorization: Bearer $TOKEN" \
 -H "Content-Type: application/json" \
 -d '{"contactId": "user_id", "reasonCode": "follow_up"}'

Review the CXone documentation for accepted reasonCode values.

1 Like

I typically get around this by ensuring the contactId in the payload matches the exact UUID format of the target user. The outbound personal connection initiation process is strict about schema validation. Verify the contact exists in the correct org scope.

{
 "contactId": "uuid-here",
 "reasonCode": "Follow up"
}
1 Like