# Twilio Application Connect

### Twilio Application Connect – Quickstart

Twilio Application Connect lets you hand off calls from your own Twilio apps into Retreaver using a **signed payload**, instead of wiring every inbound DID directly to Retreaver. Your IVRs and numbers stay in Twilio; Retreaver receives an authenticated request that says exactly which campaign and company to route the call to.

---

**In this quickstart you will learn:**

- [1. Prerequisites](#1-prerequisites)
- [2. What You Send to Retreaver](#2-what-you-send-to-retreaver)
- [3. Example TwiML Hand‑Off](#3-example-twiml-hand-off)
- [4. Setting it up via Twilio Functions](#4-setting-it-up-via-twilio-functions)
- [5. Minimal Code Examples](#5-minimal-code-examples)

---

### 1. Prerequisites

- Twilio account with a Voice application (Studio Flow, Function, or webhook).
- Retreaver account with:
  - **Twilio Application Connect** feature enabled. You should contact support to get this enabled.
  - At least one **Retreaver number** (campaign number).
  - Access to the company’s **Twilio Application Connect secret** (visible on the Company page for superusers).
  - **Twilio Application SID** . Reach out to our support team to receive your Application SID.

![](/media/4e/4eb1b886c1deb6c9202168a24e37688f76feb7977ee4a77c83350aa131bc1997.png)

> **Keep the secret safe:** Treat the Twilio Application Connect secret like a password. Never expose it in client-side code, logs, or public repositories.

---

### 2. What You Send to Retreaver

When your Twilio app is ready to hand a call to Retreaver, it:

1. Uses `<Dial><Application>` to dial your **Retreaver TwiML Application**.
2. Sends a small signed payload using `<Parameter>`s:
   - `OriginalTo` – the number originally dialed in your Twilio app.
   - `OriginalCallSid` – the Twilio `CallSid` of the original call leg.
   - `RetreaverPhoneNumber` – the Retreaver campaign number you want to route to.
   - `RetreaverCompanyId` – the Retreaver company ID.
   - `RetreaverSignature` – HMAC-SHA256 of all the above using your Retreaver company secret.

Retreaver recomputes the same signature; if it matches, the call is routed as if it had dialed `RetreaverPhoneNumber` directly.

### 3. Example TwiML Hand‑Off

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Dial>
    <Application applicationSid="APXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">
      <Parameter name="OriginalTo" value="+14155550123" />
      <Parameter name="OriginalCallSid" value="CA1234567890abcdef1234567890abcdef" />
      <Parameter name="RetreaverPhoneNumber" value="+18005551234" />
      <Parameter name="RetreaverCompanyId" value="1234" />
      <Parameter name="RetreaverSignature" value="hmac_sha256_hex_here" />
    </Application>
  </Dial>
</Response>
```

Your Twilio app code is responsible for computing `RetreaverSignature` using the canonical string and the Retreaver company secret.

---

### 4. Setting it up via Twilio Functions

You could also set it up directly in the Twilio Console by using [Twilio Functions](https://www.twilio.com/docs/serverless/functions-assets/functions) .

1. Add [crypto-js](https://www.npmjs.com/package/crypto-js) as a dependency to your function. Prefer using the latest version, i.e. set the version to "latest".
2. Add the following environment variables to your function:
 - RETREAVER_APPLICATION_SID  - Reach out to our support team to receive your Application SID
 - RETREAVER_SECRET - Follow these steps outlined in [Prerequisites](#1-prerequisites) to find out what the value should be
 - RETREAVER_COMPANY_ID - Your Retreaver company id.
 - RETREAVER_NUMBER - The number associated to the Retreaver Campaign that you'd like to receive a call to.

3. Add the following code to your function:
```javascript
// This is your new function. To start, set the name and path on the left.
const CryptoJS = require("crypto-js");

exports.handler = function(context, event, callback) { 
  const originalTo = event.To;
  const originalCallSid = event.CallSid;

  const canonical = `${originalTo}:${originalCallSid}:${context.RETREAVER_NUMBER}:${context.RETREAVER_COMPANY_ID}`;
  const signature = CryptoJS.HmacSHA256(canonical, context.RETREAVER_SECRET).toString(CryptoJS.enc.Hex);

  const twiml = new Twilio.twiml.VoiceResponse();
  const dial = twiml.dial();

  const application = dial.application();
  application.applicationSid(context.RETREAVER_APPLICATION_SID);

  application.parameter({ name: 'OriginalTo', value: originalTo });
  application.parameter({ name: 'OriginalCallSid', value: originalCallSid });
  application.parameter({ name: 'RetreaverPhoneNumber', value: context.RETREAVER_NUMBER });
  application.parameter({ name: 'RetreaverCompanyId', value: String(context.RETREAVER_COMPANY_ID) });
  application.parameter({ name: 'RetreaverSignature', value: signature });
  
  console.log(twiml.toString());

  return callback(null, twiml);
};
```

--- 

### 5. Minimal Code Examples

#### Python

```python
import hmac
import hashlib

from twilio.twiml.voice_response import VoiceResponse, Dial, Application

original_to = "+14155550123"
original_call_sid = "CA1234567890abcdef1234567890abcdef"
retreaver_number = "+18005551234"
retreaver_company_id = 1234
company_secret = "YOUR_RETREAVER_TWILIO_APP_CONNECT_SECRET"
retreaver_application_sid = "APXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

canonical = f"{original_to}:{original_call_sid}:{retreaver_number}:{retreaver_company_id}"
signature = hmac.new(
    company_secret.encode("utf-8"),
    canonical.encode("utf-8"),
    hashlib.sha256,
).hexdigest()

response = VoiceResponse()
dial = Dial()

application = Application()
application.application_sid(retreaver_application_sid)

application.parameter(name="OriginalTo", value=original_to)
application.parameter(name="OriginalCallSid", value=original_call_sid)
application.parameter(name="RetreaverPhoneNumber", value=retreaver_number)
application.parameter(name="RetreaverCompanyId", value=str(retreaver_company_id))
application.parameter(name="RetreaverSignature", value=signature)

dial.append(application)
response.append(dial)

print(str(response))
```

#### Node.js

```javascript
const CryptoJS = require('crypto-js');
const twilio = require('twilio');

const originalTo = '+14155550123';
const originalCallSid = 'CA1234567890abcdef1234567890abcdef';
const retreaverNumber = '+18005551234';
const retreaverCompanyId = 1234;
const companySecret = 'YOUR_RETREAVER_TWILIO_APP_CONNECT_SECRET';
const retreaverApplicationSid = 'APXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';

const canonical = `${originalTo}:${originalCallSid}:${retreaverNumber}:${retreaverCompanyId}`;
const signature = CryptoJS.HmacSHA256(canonical, companySecret).toString(CryptoJS.enc.Hex);

const twiml = new twilio.twiml.VoiceResponse();
const dial = twiml.dial();

const application = dial.application();
application.applicationSid(retreaverApplicationSid);

application.parameter({ name: 'OriginalTo', value: originalTo });
application.parameter({ name: 'OriginalCallSid', value: originalCallSid });
application.parameter({ name: 'RetreaverPhoneNumber', value: retreaverNumber });
application.parameter({ name: 'RetreaverCompanyId', value: String(retreaverCompanyId) });
application.parameter({ name: 'RetreaverSignature', value: signature });

console.log(twiml.toString());
```

#### Ruby

```ruby
require "openssl"
require "twilio-ruby"

original_to          = "+14155550123"
original_call_sid    = "CA1234567890abcdef1234567890abcdef"
retreaver_number     = "+18005551234"
retreaver_company_id = 1234
company_secret       = "YOUR_RETREAVER_TWILIO_APP_CONNECT_SECRET"
retreaver_app_sid    = "APXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

canonical = "#{original_to}:#{original_call_sid}:#{retreaver_number}:#{retreaver_company_id}"
signature = OpenSSL::HMAC.hexdigest("SHA256", company_secret, canonical)

response = Twilio::TwiML::VoiceResponse.new do |r|
  r.dial do |d|
    d.application do |app|
      app.application_sid(retreaver_app_sid)
      app.parameter(name: "OriginalTo", value: original_to)
      app.parameter(name: "OriginalCallSid", value: original_call_sid)
      app.parameter(name: "RetreaverPhoneNumber", value: retreaver_number)
      app.parameter(name: "RetreaverCompanyId", value: retreaver_company_id.to_s)
      app.parameter(name: "RetreaverSignature", value: signature)
    end
  end
end

puts response.to_s
```

#### PHP

```php
<?php

use Twilio\TwiML\VoiceResponse;

$originalTo          = '+14155550123';
$originalCallSid     = 'CA1234567890abcdef1234567890abcdef';
$retreaverNumber     = '+18005551234';
$retreaverCompanyId  = 1234;
$companySecret       = 'YOUR_RETREAVER_TWILIO_APP_CONNECT_SECRET';
$retreaverAppSid     = 'APXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';

$canonical = sprintf(
    '%s:%s:%s:%s',
    $originalTo,
    $originalCallSid,
    $retreaverNumber,
    $retreaverCompanyId
);

$signature = hash_hmac('sha256', $canonical, $companySecret);

$response = new VoiceResponse();
$dial = $response->dial();
$application = $dial->application();
$application->applicationSid($retreaverAppSid);

$application->parameter(['name' => 'OriginalTo', 'value' => $originalTo]);
$application->parameter(['name' => 'OriginalCallSid', 'value' => $originalCallSid]);
$application->parameter(['name' => 'RetreaverPhoneNumber', 'value' => $retreaverNumber]);
$application->parameter(['name' => 'RetreaverCompanyId', 'value' => (string)$retreaverCompanyId]);
$application->parameter(['name' => 'RetreaverSignature', 'value' => $signature]);

echo $response;
```
