Open in
Connect from NICE CXone
Send NICE CXone calls to a ThunderPhone agent from a Studio script with the ContactID in a SIP header, and look up the agent
Your CXone Studio script places a call to the agent with SIP headers that carry the contact id and any other context. When the agent is done, it hangs up, and a REST API action in the script fetches the hand-off.
Before you start
- A ThunderPhone agent and an organization API key.
- A CXone SIP trunk group that accepts custom headers. Your NICE account representative has to turn this setting on before CXone sends them.
1. Create the SIP endpoint
Placecall dials a phone number over a CXone trunk group, not a SIP address.
NICE doesn't document SIP credentials for it, and another AI provider's CXone
integration uses TLS with an IP allowlist. So create an ip_allowlist
endpoint with the number the script will dial as a dial-in number (see
Platforms that dial a phone number):
curl -X POST https://api.thunderphone.com/v1/sip-endpoints \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": 12,
"name": "NICE CXone",
"auth": "ip_allowlist",
"allowed_source_cidrs": ["CXONE_SIGNALLING_RANGE_1", "CXONE_SIGNALLING_RANGE_2"],
"dial_in_numbers": ["+14155550188"]
}'allowed_source_cidrs: the SIP signalling ranges of your CXone cluster, from NICE. Each must be a public IPv4 range of/16or narrower (IPv6/48or narrower).dial_in_numbers: the number Placecall will dial, written the way CXone sends it. It doesn't have to be a real phone number. It can't already be in use on ThunderPhone, as a phone number or on another endpoint: that returns409.
CXone's addresses are shared by all its customers, so any other CXone customer who dials the number reaches your agent. Where you choose the number, pick a long one nobody would guess (up to 15 digits), make sure CXone sends it to ThunderPhone rather than out to the phone network, and don't publish it.
2. Send calls with context
In your Studio script, before Placecall:
- Add a Sipputheader action with header
X-Call-IDand the value ofContactID. CXone sends no call-id header of its own; ThunderPhone stores this one as the call'sexternal_call_id. - Add a Sipputheader action for each other value the agent should know,
such as
X-Skillset tosupport. It reaches the prompt as{{sip_x_skill}}. Sipputheader takesUser-to-User, anyX-header, and mostP-headers; NICE recommends values of 256 characters or less.
Then Placecall to that number, over a trunk group that sends it to
sip.thunderphone.com with the number in both the request URI and the To
header. The endpoint takes TLS (port 5061) or TCP (port 5060) and refuses
UDP, and NICE doesn't document the trunk's transport, so make sure it isn't
UDP.
3. Get the call back
CXone reads SIP headers only on the INVITE and its final response, so the
agent returns the call: it says goodbye and hangs up, and your script picks the
caller up again. Add this transfer number (see
Add the transfer number):
{"name": "NICE CXone", "action": "return"}NICE doesn't document that a script continues after Placecall when the placed
call ends. Other AI providers' CXone integrations instead signal the script
through CXone's Signal API (POST /interactions/{contactId}/signal) before
they hang up; ThunderPhone doesn't call it. Confirm with NICE how your script
takes the caller back, then fetch the hand-off with a REST API action:
GET https://api.thunderphone.com/v1/calls/handoff?external_call_id=followed byContactID.- Header
Authorization: Bearer sk_live_…. - Read
handoff.summaryandhandoff.intentfrom the response to route the contact.
See Look up a handed-off call.
Test it
Call a number that runs the script, ask the agent for a person, and check that
the script continues and the REST API action returns the hand-off. If the call
never reaches the agent, check the number CXone sends, that its source address
is in allowed_source_cidrs, and that the call came over TCP or TLS. Then open the
call with GET /v1/calls/{call_id}: sip_headers should list x-call-id, and
external_call_id should equal the ContactID.
Limits
- CXone sends and reads headers only on the
INVITEand its final2xx, so nothing on the agent'sBYEreaches the script. - NICE doesn't document accepting a
REFERfrom the agent. - The REST API action times out after 10 seconds by default (under 90 at most) and reads responses up to 32 KB.