ThunderPhone 2.0 is live.Self-serve, from 2¢/min.Read the announcement

Contact centers

Connect from Microsoft Dynamics 365

Send Dynamics 365 Contact Center and Copilot Studio calls to a ThunderPhone agent through your SBC with X-headers, and look up the agent

Dynamics 365 Contact Center sends the caller to the agent through your session border controller (SBC), with up to five X-headers including the conversation id. When the agent is done, it hangs up, your SBC brings the caller back into Dynamics 365, and an HTTP Request node fetches the hand-off.

Before you start

  • A ThunderPhone agent and an organization API key.
  • The Dynamics 365 Contact Center voice channel, connected through Azure Communication Services Direct Routing to an SBC you run (SBC requirements): a supported SBC with a public certificate, TLS 1.2 on port 5061 and SRTP toward Microsoft.
  • SIP X-header support on the Transfer conversation node (Copilot Studio). Confirm it is available in your environment.

Dynamics 365 transfers only to a phone number, and Microsoft authenticates Direct Routing by certificate, not by password. Your SBC sits between Microsoft and ThunderPhone and turns that number into the agent's SIP address.

1. Create the SIP endpoint

The call reaches ThunderPhone from your SBC, so create a standard endpoint for the SBC to use:

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": "Dynamics 365 SBC"}'

Store the password from the response straight away; it is shown once, and your SBC answers ThunderPhone's challenge with it. If your SBC can't do digest authentication, create the endpoint with auth set to ip_allowlist and your SBC's public address instead; see Platforms that authenticate by source IP.

2. Send calls with context

  1. Pick a phone number for the agent on your SBC, such as +14155550188.
  2. On the SBC, route calls to that number to the endpoint's sip_uri, for example sip:agent-12-jhxmginwjx@sip.thunderphone.com, over TLS on port 5061. ThunderPhone finds the endpoint by the user part (agent-12-jhxmginwjx), which must be in both the request URI and the To header. Pass the X-headers through unchanged.
  3. In Copilot Studio, add a Transfer conversation node with External phone number transfer to that number, and add the X-headers:
    • X-Call-ID: the Dynamics 365 conversation id. No Microsoft header carries it, so add it here; ThunderPhone stores it as the call's external_call_id. Confirm in Copilot Studio which variable holds the conversation id.
    • Up to four more, such as X-Customer-Tier.

Microsoft sends at most five X-headers, with names up to 64 characters and values up to 256, using letters, digits and = ; . ! % * _ + ~ -. It writes the prefix as lowercase x-; ThunderPhone matches header names ignoring case, so x-customer-tier reaches the prompt as {{sip_x_customer_tier}}.

If you build the call with Azure Communication Services Call Automation instead, AddSipX writes X-MS-Custom- names by default. Pass SipHeaderPrefix.X so X-Call-ID keeps its name (custom context).

3. Get the call back

The agent returns the call: it says goodbye and hangs up. Add this transfer number (see Add the transfer number):

{"name": "Dynamics 365", "action": "return"}

Bringing the caller back into Dynamics 365 is your SBC's job. Microsoft documents one way in for a call with context: a new call through the SBC to a number registered in Dynamics 365, with UUI whose keys match context variables you set up under Workstreams → Advanced settings (third-party IVR transfer). Work out with your SBC vendor how the caller reaches that number when ThunderPhone hangs up, and carry the conversation id you sent in X-Call-ID so the flow can find the call.

Then fetch the hand-off with a Copilot Studio HTTP Request node:

  • GET https://api.thunderphone.com/v1/calls/handoff?external_call_id= followed by the conversation id.
  • Header Authorization: Bearer sk_live_….
  • Parse the response into a variable and use handoff.summary and handoff.intent.

See Look up a handed-off call.

Test it

Call a Dynamics 365 number that reaches the transfer node, ask the agent for a person, and check that the caller comes back into Dynamics 365. Then open the call with GET /v1/calls/{call_id}: sip_headers should list x-call-id, and external_call_id should be the conversation id. If the call never reaches the agent and your SBC logs SIP 404, its request URI or To header doesn't carry the endpoint's user part.

Limits

  • An SBC is required. Microsoft can't dial a SIP address or answer a digest challenge.
  • Microsoft sends at most five X-headers, and keeps only the first five on a call coming in. Dynamics 365 takes at most 128 characters of UUI.
  • Microsoft doesn't document reading headers on a BYE, so the hand-off comes back only through the lookup.