Architect Expression: Strip +1 and Format Phone Number to (XXX) XXX-XXXX

Need to write an Architect expression that takes a raw phone number like +12025551234 and outputs (202) 555-1234. The input comes from the data action as a string. I’ve tried using replace and substring but it’s getting messy with the variable length. What’s the cleanest way to parse the country code and add the parentheses and dash without using a custom script?

It’s actually a bit of a pain to do purely in Architect expressions if the input length varies, because you don’t have a native regex_replace function available in the standard expression library. You’ll end up nesting substring calls which gets messy fast, exactly as you mentioned.

If you’re open to a tiny bit of JavaScript, it’s infinitely cleaner. You can use a Script data action with a simple regex. Here’s the payload you’d send to the /api/v2/analytics/details/query endpoint to trigger it, or just drop this JS into an Architect Script action:

// Input: +12025551234
var raw = data.input.phoneNumber; 

// Strip non-digits first to be safe
var digits = raw.replace(/\D/g, '');

// Check if it starts with 1 and is 11 digits
if (digits.length === 11 && digits.startsWith('1')) {
 digits = digits.substring(1);
}

// Format (XXX) XXX-XXXX
var formatted = '(' + digits.substring(0,3) + ') ' + digits.substring(3,6) + '-' + digits.substring(6,10);

data.output.formattedPhone = formatted;

If you absolutely must stick to expressions, you can try this chain, but it assumes the input is always exactly 12 characters starting with +1. It’s brittle, but it works for strict environments:

concat(
 "(",
 substring(data.input.phoneNumber, 2, 3),
 ") ",
 substring(data.input.phoneNumber, 5, 3),
 "-",
 substring(data.input.phoneNumber, 8, 4)
)

Just be careful with the indices. substring in Genesys is usually 0-indexed and takes the start position and length. So if your string is +12025551234:

  • Index 0 is +
  • Index 1 is 1
  • Index 2 is 2 (start of area code)
  • Length 3 gets 202

You’ll need to test the exact offset based on whether the + is present or not. I usually just add a previous action to strip the + using replace(data.input.phoneNumber, "+", "") to make the indexing predictable. Then the expression becomes:

concat(
 "(",
 substring(data.input.phoneNumber, 1, 3),
 ") ",
 substring(data.input.phoneNumber, 4, 3),
 "-",
 substring(data.input.phoneNumber, 7, 4)
)

That’s much easier to maintain. Just remember to handle cases where the number might be 10 digits already (no country code) or 11 digits without the +. A script is definitely the safer bet for production flows.