diff --git a/README.md b/README.md
index c3dbb35..b720d09 100644
--- a/README.md
+++ b/README.md
@@ -92,6 +92,35 @@ $response = BandwidthLib\Voice\Bxml\Response::make()
echo $response->toBxml();
```
+### Create A Refer BXML
+
+```php
+
+$sipUri = new BandwidthLib\Voice\Bxml\SipUri("sip:alice@atlanta.example.com");
+$refer = new BandwidthLib\Voice\Bxml\Refer();
+$refer->referCompleteUrl("https://example.com/handleRefer");
+$refer->referCompleteMethod("POST");
+$refer->sipUri($sipUri);
+
+$response = new BandwidthLib\Voice\Bxml\Response();
+$response->addVerb($refer);
+echo $response->toBxml();
+```
+
+> **Note:** On success, the call is terminated — the remote SIP endpoint redirects away from Bandwidth entirely. Use `referCompleteUrl` only for failure recovery.
+
+```php
+// Failure recovery example in your referCompleteUrl handler:
+$requestBody = json_decode(file_get_contents('php://input'), true);
+if ($requestBody['referCallStatus'] === 'failure') {
+ // Handle failure: play a message or redirect
+ $speakSentence = new BandwidthLib\Voice\Bxml\SpeakSentence("The transfer failed. Please try again.");
+ $response = new BandwidthLib\Voice\Bxml\Response();
+ $response->addVerb($speakSentence);
+ echo $response->toBxml();
+}
+```
+
### Create A MFA Request
```php
diff --git a/src/Voice/Bxml/Refer.php b/src/Voice/Bxml/Refer.php
new file mode 100644
index 0000000..c12f107
--- /dev/null
+++ b/src/Voice/Bxml/Refer.php
@@ -0,0 +1,97 @@
+referCompleteUrl = $referCompleteUrl;
+ return $this;
+ }
+
+ /**
+ * Sets the referCompleteMethod attribute for Refer
+ *
+ * @param string $referCompleteMethod The HTTP method for the refer complete callback (GET or POST)
+ */
+ public function referCompleteMethod(string $referCompleteMethod): Refer {
+ $this->referCompleteMethod = $referCompleteMethod;
+ return $this;
+ }
+
+ /**
+ * Sets the tag attribute for Refer
+ *
+ * @param string $tag A custom string to be included in callbacks
+ */
+ public function tag(string $tag): Refer {
+ $this->tag = $tag;
+ return $this;
+ }
+
+ /**
+ * Sets the SipUri child element for Refer
+ *
+ * @param SipUri $sipUri The SipUri destination for the REFER
+ */
+ public function sipUri(SipUri $sipUri): Refer {
+ $this->sipUri = $sipUri;
+ return $this;
+ }
+
+ public function toBxml(DOMDocument $doc): DOMElement {
+ $element = $doc->createElement("Refer");
+
+ if(isset($this->referCompleteUrl)) {
+ $element->setAttribute("referCompleteUrl", $this->referCompleteUrl);
+ }
+
+ if(isset($this->referCompleteMethod)) {
+ $element->setAttribute("referCompleteMethod", $this->referCompleteMethod);
+ }
+
+ if(isset($this->tag)) {
+ $element->setAttribute("tag", $this->tag);
+ }
+
+ if(isset($this->sipUri)) {
+ $element->appendChild($this->sipUri->toBxml($doc));
+ }
+
+ return $element;
+ }
+}
+
diff --git a/src/Voice/Models/ReferCompleteCallback.php b/src/Voice/Models/ReferCompleteCallback.php
new file mode 100644
index 0000000..b7866a4
--- /dev/null
+++ b/src/Voice/Models/ReferCompleteCallback.php
@@ -0,0 +1,154 @@
+eventType = func_get_arg(0);
+ $this->eventTime = func_get_arg(1);
+ $this->accountId = func_get_arg(2);
+ $this->applicationId = func_get_arg(3);
+ $this->from = func_get_arg(4);
+ $this->to = func_get_arg(5);
+ $this->direction = func_get_arg(6);
+ $this->callId = func_get_arg(7);
+ $this->callUrl = func_get_arg(8);
+ $this->startTime = func_get_arg(9);
+ $this->answerTime = func_get_arg(10);
+ $this->referCallStatus = func_get_arg(11);
+ $this->referSipResponseCode = func_get_arg(12);
+ $this->notifySipResponseCode = func_get_arg(13);
+ $this->tag = func_get_arg(14);
+ }
+ }
+
+ /**
+ * Encode this object to JSON
+ */
+ public function jsonSerialize(): array
+ {
+ $json = array();
+ $json['eventType'] = $this->eventType;
+ $json['eventTime'] = $this->eventTime;
+ $json['accountId'] = $this->accountId;
+ $json['applicationId'] = $this->applicationId;
+ $json['from'] = $this->from;
+ $json['to'] = $this->to;
+ $json['direction'] = $this->direction;
+ $json['callId'] = $this->callId;
+ $json['callUrl'] = $this->callUrl;
+ $json['startTime'] = $this->startTime;
+ $json['answerTime'] = $this->answerTime;
+ $json['referCallStatus'] = $this->referCallStatus;
+ $json['referSipResponseCode'] = $this->referSipResponseCode;
+ $json['notifySipResponseCode'] = $this->notifySipResponseCode;
+ $json['tag'] = $this->tag;
+
+ return array_filter($json);
+ }
+}
+
diff --git a/tests/BxmlTest.php b/tests/BxmlTest.php
index 44bdb2f..62809cf 100644
--- a/tests/BxmlTest.php
+++ b/tests/BxmlTest.php
@@ -540,4 +540,33 @@ public function testStopTranscription() {
$responseXml = $response->toBxml();
$this->assertEquals($expectedXml, $responseXml);
}
+
+ public function testRefer() {
+ $sipUri = new BandwidthLib\Voice\Bxml\SipUri("sip:alice@atlanta.example.com");
+ $refer = new BandwidthLib\Voice\Bxml\Refer();
+ $refer->referCompleteUrl("https://example.com/handleRefer");
+ $refer->referCompleteMethod("POST");
+ $refer->tag("my-tag");
+ $refer->sipUri($sipUri);
+
+ $response = new BandwidthLib\Voice\Bxml\Response();
+ $response->addVerb($refer);
+
+ $expectedXml = 'sip:alice@atlanta.example.com';
+ $responseXml = $response->toBxml();
+ $this->assertEquals($expectedXml, $responseXml);
+ }
+
+ public function testReferNoOptionalAttributes() {
+ $sipUri = new BandwidthLib\Voice\Bxml\SipUri("sip:bob@biloxi.example.com");
+ $refer = new BandwidthLib\Voice\Bxml\Refer();
+ $refer->sipUri($sipUri);
+
+ $response = new BandwidthLib\Voice\Bxml\Response();
+ $response->addVerb($refer);
+
+ $expectedXml = 'sip:bob@biloxi.example.com';
+ $responseXml = $response->toBxml();
+ $this->assertEquals($expectedXml, $responseXml);
+ }
}