---
title: "Connect from Five9"
description: "Send Five9 calls to a ThunderPhone agent over SIP with AI Agent Connect, and get them back with routing headers your IVR script reads."
---

Your Five9 IVR script sends the caller to the agent with Five9's call
details. When the agent is done, it hangs up with routing headers on the SIP
`BYE`, which the script reads into call variables to route the caller.

## Before you start

- A ThunderPhone agent and an organization [API key](/guides/api-keys).
- Five9's **AI Agent Connect** add-on. Five9 limits it to AI providers it has
  accredited, and Five9's implementation team sets it up: it imports the
  provider's IVR script template, creates the call variables and points the
  script's **Third Party Transfer** module at the provider. ThunderPhone isn't
  on Five9's accredited list yet: ask your Five9 account team or ThunderPhone
  support before you plan around it.

## 1. Create the SIP endpoint

Five9's Third Party Transfer module dials a phone number, not a SIP address,
and other providers' Five9 integrations authenticate Five9 by source address
rather than a password. So create an `ip_allowlist` endpoint with the number
Five9 will dial as a dial-in number (see
[Platforms that dial a phone number](/guides/sip-addresses#platforms-that-dial-a-phone-number)):

```bash
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": "Five9",
    "auth": "ip_allowlist",
    "allowed_source_cidrs": ["FIVE9_SIGNALLING_RANGE_1", "FIVE9_SIGNALLING_RANGE_2"],
    "dial_in_numbers": ["+14155550188"]
  }'
```

- `allowed_source_cidrs`: the SIP signalling ranges of your Five9 data
  centers, from Five9. Each must be a public IPv4 range of `/16` or narrower
  (IPv6 `/48` or narrower).
- `dial_in_numbers`: the number Five9's script will dial, written the way
  Five9 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
  returns `409`.

Five9's addresses are shared by all its customers, so any other Five9
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
Five9 sends it to ThunderPhone rather than out to the phone network, and
don't publish it.

## 2. Send calls with context

Ask Five9's implementation team to:

- Send the call from the **Third Party Transfer** module to
  `sip:+14155550188@sip.thunderphone.com`, with the number in both the request
  URI and the `To` header. The module takes the number, with the provider's
  SIP domain in a header.
- Send it over TLS (port 5061) or TCP (port 5060). The endpoint refuses UDP,
  and Five9 doesn't publish which transport it uses, so make sure it isn't
  UDP.
- Turn on **Return After 3rd Party Call**, so the script continues when the
  agent hangs up (Five9 allows up to 3,600 seconds on the third-party call).

Five9's guide lists the values it sends (`call.ANI`, `call.DNIS`,
`call.call_id`, `call.session_id`, `call.campaign_name` and others), not their
header names. Other AI providers' Five9 integrations document them on the wire
as `X-CallANI`, `X-CallDNIS`, `X-CallID`, `X-CallSessionID`, `X-CallCampaign`
and `X-AgentID`; check them on your first test call. Each reaches the prompt as a variable, such as
`{{sip_x_callcampaign}}`. `X-CallID` is stored as the call's
`external_call_id`.

## 3. Get the call back

The agent returns the call: it says goodbye and hangs up, and the `BYE` carries
the four headers Five9's script reads. Add this transfer number (see
[Add the transfer number](/guides/contact-centers/overview#add-the-transfer-number)):

```json
{
  "name": "Five9 agent",
  "action": "return",
  "headers": {
    "X-RouteType": "SkillTransfer",
    "X-RouteValue": "Support",
    "X-RouteReason": "{{handoff_intent}}",
    "X-CustomMetaData": "handoff_id={{handoff_id}}"
  }
}
```

- `X-RouteType` and `X-RouteValue` tell the script where to send the caller,
  here the Support skill. Values other providers document for `X-RouteType` include
  `SkillTransfer`, `PhoneTransfer`, `Hangup` and `DispositionOnly`; agree the
  values with whoever maintains the script. For several destinations, add one
  return per destination with a different name and `X-RouteValue`.
- `X-RouteReason` carries the agent's intent label, such as `billing_dispute`.
- `X-CustomMetaData` carries the hand-off id. The `BYE` also carries it as
  `X-TP-Handoff-Id`, which Five9 doesn't read.

Five9's script maps the four headers into call variables. For the agent's
summary, have the script call the hand-off lookup with an IVR **Query** module:
`GET https://api.thunderphone.com/v1/calls/handoff?external_call_id=` followed by
`call.call_id`, with an Authorization Profile that sends
`Authorization: Bearer` and your API key. See
[Look up a handed-off call](/api-reference/calls#look-up-a-handed-off-call).

## Test it

Call into the IVR script, ask the agent for a person, and check that the script
routes the caller with the call variables filled. If the call never reaches the
agent, check that the number in the request URI and `To` header matches the
dial-in number, that Five9's 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-callid`, and
`external_call_id` should match `call.call_id` in Five9.

## Limits

- Five9's guide documents routing data on the `BYE` and doesn't mention
  accepting a `REFER`, so the hand-back is a cold transfer by the script.
- Five9 reads `X-RouteType`, `X-RouteValue`, `X-RouteReason` and
  `X-CustomMetaData`, not `User-to-User`. ThunderPhone sends each header value
  at most 256 bytes long.
- Five9 recommends keeping custom headers to about ten to avoid packet
  fragmentation.
