Campaign API 400 Bad Request: Invalid Phone Number Format During Zendesk Export

Trying to make sense of why the Genesys Cloud Campaigns API is rejecting valid phone numbers during our outbound dialer migration from Zendesk.

  • We are currently moving a high-volume outbound sales queue from Zendesk Talk to Genesys Cloud Predictive Dialing.
  • The source data in Zendesk contains phone numbers in E.164 format, specifically with leading plus signs (e.g., +33123456789 for our EU-FR region).
  • When we attempt to create a new campaign via the POST /api/v2/outbound/campaigns endpoint using the Python SDK v2.10.0, the request fails immediately.
  • The response body returns a 400 Bad Request with the specific error message: Invalid phone number format. Must be numeric only.
  • In Zendesk, we handled this by stripping non-numeric characters before import, but our current migration script assumes Genesys handles E.164 natively, similar to how it handles inbound routing.
  • We have verified that the user account creating the campaign has the outbound_campaign_manage permission set correctly.
  • The environment is the EU-FR region, and we are testing with a small batch of 50 contacts to avoid rate limiting issues.
  • We tried removing the plus sign and sending just the digits (e.g., 33123456789), but the error persists, suggesting the validation logic might be stricter than expected.
  • Is there a specific configuration setting in Admin > Outbound > Campaigns that needs to be adjusted to accept E.164 formats?
  • Or does the API require a specific phone_number_type parameter that we are missing in our JSON payload?
  • Any insights on how other Zendesk-to-GC migrations have handled this phone number validation mismatch would be appreciated.

The source data in Zendesk contains phone numbers in E.164 format, specifically with leading plus signs…

The easiest way to fix this is to verify the campaign list schema requirements. The API often rejects the ‘+’ character in specific fields. Ensure the data action strips the leading plus sign before ingestion, or map the raw E.164 string to a dedicated ‘phone_number’ attribute that accepts standard international formatting without the prefix.

How I usually solve this is by stripping the plus sign in the jmeter pre-processor before hitting the endpoint. the suggestion above is correct about the schema, but in my load tests, i found that even if the schema accepts it, the underlying campaign engine sometimes chokes on the raw e.164 string if it’s not cleaned.

here is a simple beanshell script i use in the jmeter test plan to sanitize the phone numbers from the zendesk export csv. it removes any non-digit characters, which effectively strips the ‘+’ and any dashes or spaces.

import org.apache.jmeter.config.Arguments;

String rawPhone = vars.get("phone_number");
// remove non-digits
String cleanPhone = rawPhone.replaceAll("\\D", "");

// optional: add country code if missing, assuming US for this example
if (cleanPhone.length() == 10) {
 cleanPhone = "1" + cleanPhone;
}

vars.put("clean_phone", cleanPhone);

also, watch out for rate limits on the campaign api. if you are pushing thousands of contacts at once, you will hit 429 errors. i usually set a constant throughput timer to 50 requests per second in my jmeter config to stay under the radar. the api docs say the limit is higher, but in practice, during peak hours in ap-southeast-1, it feels stricter.

another thing, make sure you are using the correct data action. if you are using a custom data action, double check the field mapping. sometimes the ui lets you map a string field to phone_number, but the backend expects an integer or a specific string format without the prefix. i had a similar issue last week where the export failed silently until i added a debug logger in the jmeter thread group.

try cleaning the data at the source or in the jmeter pre-processor. it saves a lot of headache later when the campaign actually runs and tries to dial. also, check the retry-after header if you get 429s. don’t just retry instantly, back off a bit.