From afc47c1ecf346f69592d549f7b9a6c36360ccbef Mon Sep 17 00:00:00 2001 From: atelegu Date: Fri, 22 May 2026 16:52:51 +0530 Subject: [PATCH 1/6] VAPI-3163 --- README.md | 25 ++++ docs/ReferCallStatusEnum.md | 8 ++ docs/ReferCompleteCallback.md | 24 ++++ .../Unit/Model/Bxml/TestRefer.cs | 46 +++++++ .../Unit/Model/ReferCompleteCallbackTests.cs | 58 ++++++++ .../Model/Bxml/ReferCompleteCallback.cs | 125 ++++++++++++++++++ .../Model/Bxml/Verbs/Refer.cs | 102 ++++++++++++++ .../Model/ReferCallStatusEnum.cs | 19 +++ 8 files changed, 407 insertions(+) create mode 100644 docs/ReferCallStatusEnum.md create mode 100644 docs/ReferCompleteCallback.md create mode 100644 src/Bandwidth.Standard.Test/Unit/Model/Bxml/TestRefer.cs create mode 100644 src/Bandwidth.Standard.Test/Unit/Model/ReferCompleteCallbackTests.cs create mode 100644 src/Bandwidth.Standard/Model/Bxml/ReferCompleteCallback.cs create mode 100644 src/Bandwidth.Standard/Model/Bxml/Verbs/Refer.cs create mode 100644 src/Bandwidth.Standard/Model/ReferCallStatusEnum.cs diff --git a/README.md b/README.md index 70cbdf8..4e27baa 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,31 @@ namespace Example } ``` +## BXML `` example + +```csharp +using Bandwidth.Standard.Model.Bxml; +using Bandwidth.Standard.Model.Bxml.Verbs; + +var refer = new Refer() + .WithSipUri("sip:alice@atlanta.example.com") + .WithReferCompleteUrl("https://example.com/handleRefer") + .WithReferCompleteMethod("POST") + .WithTag("handoff-123"); + +var bxml = new Response(refer).ToBXML(); + +When a REFER succeeds, the remote SIP endpoint redirects away from Bandwidth and the call is terminated. Do not expect post-success BXML execution on that call leg. + +## `referComplete` failure recovery example + +```csharp +// Example callback handler pseudocode +if (callback.ReferCallStatus == ReferCallStatusEnum.Failure) +{ + // Recover only on failure (e.g. fallback flow, retry, alternate route) +} + ## Documentation for API Endpoints diff --git a/docs/ReferCallStatusEnum.md b/docs/ReferCallStatusEnum.md new file mode 100644 index 0000000..6f190dc --- /dev/null +++ b/docs/ReferCallStatusEnum.md @@ -0,0 +1,8 @@ +# Bandwidth.Standard.Model.ReferCallStatusEnum + +## Enum + +* `Success` (value: `success`) +* `Failure` (value: `failure`) + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) \ No newline at end of file diff --git a/docs/ReferCompleteCallback.md b/docs/ReferCompleteCallback.md new file mode 100644 index 0000000..865e11c --- /dev/null +++ b/docs/ReferCompleteCallback.md @@ -0,0 +1,24 @@ +# Bandwidth.Standard.Model.ReferCompleteCallback +This event is sent to the referCompleteUrl of the A-leg's verb when the REFER attempt completes. + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**EventType** | **string** | The event type. Always `referComplete`. | [optional] +**EventTime** | **DateTime** | The approximate UTC date and time when the event was generated by the Bandwidth server. | [optional] +**AccountId** | **string** | The user account associated with the call. | [optional] +**ApplicationId** | **string** | The id of the application associated with the call. | [optional] +**From** | **string** | The provided identifier of the caller. | [optional] +**To** | **string** | The phone number that received the call. | [optional] +**Direction** | **CallDirectionEnum** | Call direction (`inbound`). | [optional] +**CallId** | **string** | The call id associated with the event. | [optional] +**CallUrl** | **string** | The URL of the call associated with the event. | [optional] +**StartTime** | **DateTime** | Time the call was started. | [optional] +**AnswerTime** | **DateTime** | Time the call was answered. | [optional] +**ReferCallStatus** | **ReferCallStatusEnum** | Whether REFER succeeded or failed. | [optional] +**Tag** | **string** | Optional custom string included in callbacks. | [optional] +**ReferSipResponseCode** | **int?** | Optional SIP response code from the REFER transaction. | [optional] +**NotifySipResponseCode** | **int?** | Optional SIP response code from the NOTIFY transaction. | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) \ No newline at end of file diff --git a/src/Bandwidth.Standard.Test/Unit/Model/Bxml/TestRefer.cs b/src/Bandwidth.Standard.Test/Unit/Model/Bxml/TestRefer.cs new file mode 100644 index 0000000..7380b5f --- /dev/null +++ b/src/Bandwidth.Standard.Test/Unit/Model/Bxml/TestRefer.cs @@ -0,0 +1,46 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using Bandwidth.Standard.Model.Bxml; +using Bandwidth.Standard.Model.Bxml.Verbs; +using Xunit; + +namespace Bandwidth.Standard.Test.Unit.Model.Bxml +{ + public class TestRefer + { + [Fact] + public void ReferRoundTripTest() + { + var expected = " sip:alice@atlanta.example.com "; + + var refer = new Refer() + .WithSipUri("sip:alice@atlanta.example.com") + .WithReferCompleteUrl("https://example.com/handleRefer") + .WithReferCompleteMethod("POST") + .WithTag("refer-tag"); + + var actual = new Response(refer).ToBXML(); + Assert.Equal(expected, actual.Replace("\n", "").Replace("\r", "")); + + const string referOnlyXml = "sip:alice@atlanta.example.com"; + var serializer = new XmlSerializer(typeof(Refer), ""); + Refer deserializedRefer; + using (var reader = new StringReader(referOnlyXml)) + { + deserializedRefer = (Refer)serializer.Deserialize(reader); + } + + Assert.Equal("sip:alice@atlanta.example.com", deserializedRefer.SipUriElement.Uri); + var roundTrip = new Response(deserializedRefer).ToBXML(); + Assert.Equal(expected, roundTrip.Replace("\n", "").Replace("\r", "")); + } + + [Fact] + public void ReferSipUriMustStartWithSipScheme() + { + var refer = new Refer(); + Assert.Throws(() => refer.WithSipUri("tel:+15551234567")); + } + } +} \ No newline at end of file diff --git a/src/Bandwidth.Standard.Test/Unit/Model/ReferCompleteCallbackTests.cs b/src/Bandwidth.Standard.Test/Unit/Model/ReferCompleteCallbackTests.cs new file mode 100644 index 0000000..bdfd4e2 --- /dev/null +++ b/src/Bandwidth.Standard.Test/Unit/Model/ReferCompleteCallbackTests.cs @@ -0,0 +1,58 @@ +using Bandwidth.Standard.Model; +using Newtonsoft.Json; +using Xunit; + +namespace Bandwidth.Standard.Test.Unit.Model +{ + public class ReferCompleteCallbackTests + { + [Fact] + public void ReferCompleteSuccessTest() + { + var callback = Deserialize("{\"eventType\":\"referComplete\",\"eventTime\":\"2024-01-01T00:00:00.000Z\",\"accountId\":\"9900000\",\"applicationId\":\"04e88489-df02-4e34-a0ee-27a91849555f\",\"from\":\"+15555550100\",\"to\":\"+15555550101\",\"direction\":\"inbound\",\"callId\":\"c-123\",\"callUrl\":\"https://voice.bandwidth.com/api/v2/accounts/9900000/calls/c-123\",\"startTime\":\"2024-01-01T00:00:00.000Z\",\"answerTime\":\"2024-01-01T00:00:01.000Z\",\"referCallStatus\":\"success\"}"); + + Assert.Equal(ReferCallStatusEnum.Success, callback.ReferCallStatus); + Assert.Null(callback.ReferSipResponseCode); + Assert.Null(callback.NotifySipResponseCode); + } + + [Fact] + public void ReferCompleteReferRejectedTest() + { + var callback = Deserialize("{\"eventType\":\"referComplete\",\"eventTime\":\"2024-01-01T00:00:00.000Z\",\"accountId\":\"9900000\",\"applicationId\":\"04e88489-df02-4e34-a0ee-27a91849555f\",\"from\":\"+15555550100\",\"to\":\"+15555550101\",\"direction\":\"inbound\",\"callId\":\"c-123\",\"callUrl\":\"https://voice.bandwidth.com/api/v2/accounts/9900000/calls/c-123\",\"startTime\":\"2024-01-01T00:00:00.000Z\",\"answerTime\":\"2024-01-01T00:00:01.000Z\",\"referCallStatus\":\"failure\",\"referSipResponseCode\":405}"); + + Assert.Equal(ReferCallStatusEnum.Failure, callback.ReferCallStatus); + Assert.Equal(405, callback.ReferSipResponseCode); + Assert.Null(callback.NotifySipResponseCode); + } + + [Fact] + public void ReferCompleteDestinationUnreachableTest() + { + var callback = Deserialize("{\"eventType\":\"referComplete\",\"eventTime\":\"2024-01-01T00:00:00.000Z\",\"accountId\":\"9900000\",\"applicationId\":\"04e88489-df02-4e34-a0ee-27a91849555f\",\"from\":\"+15555550100\",\"to\":\"+15555550101\",\"direction\":\"inbound\",\"callId\":\"c-123\",\"callUrl\":\"https://voice.bandwidth.com/api/v2/accounts/9900000/calls/c-123\",\"startTime\":\"2024-01-01T00:00:00.000Z\",\"answerTime\":\"2024-01-01T00:00:01.000Z\",\"referCallStatus\":\"failure\",\"referSipResponseCode\":202,\"notifySipResponseCode\":486}"); + + Assert.Equal(ReferCallStatusEnum.Failure, callback.ReferCallStatus); + Assert.Equal(202, callback.ReferSipResponseCode); + Assert.Equal(486, callback.NotifySipResponseCode); + } + + [Fact] + public void ReferCompleteNotifyTimeoutTest() + { + var callback = Deserialize("{\"eventType\":\"referComplete\",\"eventTime\":\"2024-01-01T00:00:00.000Z\",\"accountId\":\"9900000\",\"applicationId\":\"04e88489-df02-4e34-a0ee-27a91849555f\",\"from\":\"+15555550100\",\"to\":\"+15555550101\",\"direction\":\"inbound\",\"callId\":\"c-123\",\"callUrl\":\"https://voice.bandwidth.com/api/v2/accounts/9900000/calls/c-123\",\"startTime\":\"2024-01-01T00:00:00.000Z\",\"answerTime\":\"2024-01-01T00:00:01.000Z\",\"referCallStatus\":\"failure\",\"referSipResponseCode\":202}"); + + Assert.Equal(ReferCallStatusEnum.Failure, callback.ReferCallStatus); + Assert.Equal(202, callback.ReferSipResponseCode); + Assert.Null(callback.NotifySipResponseCode); + } + + private static ReferCompleteCallback Deserialize(string json) + { + var callback = JsonConvert.DeserializeObject(json); + Assert.NotNull(callback); + Assert.Equal("referComplete", callback.EventType); + Assert.Equal(CallDirectionEnum.Inbound, callback.Direction); + return callback; + } + } +} \ No newline at end of file diff --git a/src/Bandwidth.Standard/Model/Bxml/ReferCompleteCallback.cs b/src/Bandwidth.Standard/Model/Bxml/ReferCompleteCallback.cs new file mode 100644 index 0000000..ea0b105 --- /dev/null +++ b/src/Bandwidth.Standard/Model/Bxml/ReferCompleteCallback.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; +using System.Text; + +namespace Bandwidth.Standard.Model +{ + /// This event is sent to the referCompleteUrl of the A-leg's <Refer> verb when the REFER attempt completes. + [DataContract(Name = "referCompleteCallback")] + public partial class ReferCompleteCallback : IValidatableObject + { + public ReferCompleteCallback( + string eventType = default(string), + DateTime eventTime = default(DateTime), + string accountId = default(string), + string applicationId = default(string), + string from = default(string), + string to = default(string), + CallDirectionEnum? direction = default(CallDirectionEnum?), + string callId = default(string), + string callUrl = default(string), + DateTime startTime = default(DateTime), + DateTime answerTime = default(DateTime), + ReferCallStatusEnum referCallStatus = default(ReferCallStatusEnum), + string tag = default(string), + int? referSipResponseCode = default(int?), + int? notifySipResponseCode = default(int?)) + { + EventType = eventType; + EventTime = eventTime; + AccountId = accountId; + ApplicationId = applicationId; + From = from; + To = to; + Direction = direction; + CallId = callId; + CallUrl = callUrl; + StartTime = startTime; + AnswerTime = answerTime; + ReferCallStatus = referCallStatus; + Tag = tag; + ReferSipResponseCode = referSipResponseCode; + NotifySipResponseCode = notifySipResponseCode; + } + + [DataMember(Name = "eventType", EmitDefaultValue = false)] + public string EventType { get; set; } + + [DataMember(Name = "eventTime", EmitDefaultValue = false)] + public DateTime EventTime { get; set; } + + [DataMember(Name = "accountId", EmitDefaultValue = false)] + public string AccountId { get; set; } + + [DataMember(Name = "applicationId", EmitDefaultValue = false)] + public string ApplicationId { get; set; } + + [DataMember(Name = "from", EmitDefaultValue = false)] + public string From { get; set; } + + [DataMember(Name = "to", EmitDefaultValue = false)] + public string To { get; set; } + + [DataMember(Name = "direction", EmitDefaultValue = false)] + public CallDirectionEnum? Direction { get; set; } + + [DataMember(Name = "callId", EmitDefaultValue = false)] + public string CallId { get; set; } + + [DataMember(Name = "callUrl", EmitDefaultValue = false)] + public string CallUrl { get; set; } + + [DataMember(Name = "startTime", EmitDefaultValue = false)] + public DateTime StartTime { get; set; } + + [DataMember(Name = "answerTime", EmitDefaultValue = false)] + public DateTime AnswerTime { get; set; } + + [DataMember(Name = "referCallStatus", EmitDefaultValue = false)] + public ReferCallStatusEnum ReferCallStatus { get; set; } + + [DataMember(Name = "tag", EmitDefaultValue = true)] + public string Tag { get; set; } + + [DataMember(Name = "referSipResponseCode", EmitDefaultValue = true)] + public int? ReferSipResponseCode { get; set; } + + [DataMember(Name = "notifySipResponseCode", EmitDefaultValue = true)] + public int? NotifySipResponseCode { get; set; } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class ReferCompleteCallback {\n"); + sb.Append(" EventType: ").Append(EventType).Append("\n"); + sb.Append(" EventTime: ").Append(EventTime).Append("\n"); + sb.Append(" AccountId: ").Append(AccountId).Append("\n"); + sb.Append(" ApplicationId: ").Append(ApplicationId).Append("\n"); + sb.Append(" From: ").Append(From).Append("\n"); + sb.Append(" To: ").Append(To).Append("\n"); + sb.Append(" Direction: ").Append(Direction).Append("\n"); + sb.Append(" CallId: ").Append(CallId).Append("\n"); + sb.Append(" CallUrl: ").Append(CallUrl).Append("\n"); + sb.Append(" StartTime: ").Append(StartTime).Append("\n"); + sb.Append(" AnswerTime: ").Append(AnswerTime).Append("\n"); + sb.Append(" ReferCallStatus: ").Append(ReferCallStatus).Append("\n"); + sb.Append(" Tag: ").Append(Tag).Append("\n"); + sb.Append(" ReferSipResponseCode: ").Append(ReferSipResponseCode).Append("\n"); + sb.Append(" NotifySipResponseCode: ").Append(NotifySipResponseCode).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + yield break; + } + } +} \ No newline at end of file diff --git a/src/Bandwidth.Standard/Model/Bxml/Verbs/Refer.cs b/src/Bandwidth.Standard/Model/Bxml/Verbs/Refer.cs new file mode 100644 index 0000000..fd93825 --- /dev/null +++ b/src/Bandwidth.Standard/Model/Bxml/Verbs/Refer.cs @@ -0,0 +1,102 @@ +using Bandwidth.Standard.Model.Bxml; +using System; +using System.Xml.Serialization; + +namespace Bandwidth.Standard.Model.Bxml.Verbs +{ + /// The Refer verb is used to hand off a call to a SIP endpoint. + /// + public class Refer : IVerb + { + private string referCompleteMethod; + + /// URL to receive the refer complete callback. + [XmlAttribute("referCompleteUrl")] + public string ReferCompleteUrl { get; set; } + + /// HTTP method to send the refer complete callback. + [XmlAttribute("referCompleteMethod")] + public string ReferCompleteMethod + { + get { return referCompleteMethod; } + set + { + if (value != null && value != "GET" && value != "POST") + { + throw new ArgumentException("ReferCompleteMethod must be either 'GET' or 'POST'."); + } + referCompleteMethod = value; + } + } + + /// Optional custom string to include in callbacks. + [XmlAttribute("tag")] + public string Tag { get; set; } + + /// SIP URI destination for the REFER. + [XmlElement("SipUri")] + public SipUri SipUriElement { get; set; } + + /// Initializes a new instance of the Refer class. + public Refer() + { + ReferCompleteMethod = "POST"; + } + + /// Sets the SIP URI destination from a string. + public Refer WithSipUri(string sipUri) + { + SipUriElement = new SipUri { Uri = sipUri }; + return this; + } + + /// Sets the SIP URI destination from a SipUri object. + public Refer WithSipUri(SipUri sipUri) + { + SipUriElement = sipUri; + return this; + } + + /// Sets referCompleteUrl. + public Refer WithReferCompleteUrl(string referCompleteUrl) + { + ReferCompleteUrl = referCompleteUrl; + return this; + } + + /// Sets referCompleteMethod. + public Refer WithReferCompleteMethod(string referCompleteMethod) + { + ReferCompleteMethod = referCompleteMethod; + return this; + } + + /// Sets tag. + public Refer WithTag(string tag) + { + Tag = tag; + return this; + } + + /// BXML tag to represent a SIP URI for the refer verb. + public class SipUri : IVerb + { + private string _uri; + + /// SIP URI to refer the call to (must start with sip:). + [XmlText] + public string Uri + { + get { return _uri; } + set + { + if (value != null && !value.StartsWith("sip:", StringComparison.OrdinalIgnoreCase)) + { + throw new ArgumentException("SipUri must start with 'sip:'."); + } + _uri = value; + } + } + } + } +} \ No newline at end of file diff --git a/src/Bandwidth.Standard/Model/ReferCallStatusEnum.cs b/src/Bandwidth.Standard/Model/ReferCallStatusEnum.cs new file mode 100644 index 0000000..ad80039 --- /dev/null +++ b/src/Bandwidth.Standard/Model/ReferCallStatusEnum.cs @@ -0,0 +1,19 @@ +using System.Runtime.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; + +namespace Bandwidth.Standard.Model +{ + /// Result of a refer attempt. + [JsonConverter(typeof(StringEnumConverter))] + public enum ReferCallStatusEnum + { + /// Enum Success for value: success + [EnumMember(Value = "success")] + Success = 1, + + /// Enum Failure for value: failure + [EnumMember(Value = "failure")] + Failure = 2 + } +} \ No newline at end of file From 8c101d6adcc4ca80380cfbd6b035668fe2df6186 Mon Sep 17 00:00:00 2001 From: atelegu Date: Tue, 26 May 2026 17:22:13 +0530 Subject: [PATCH 2/6] VAPI-3163 --- docs/ReferCallStatusEnum.md | 8 -- docs/ReferCompleteCallback.md | 24 ---- .../Unit/Model/ReferCompleteCallbackTests.cs | 58 -------- .../Model/Bxml/ReferCompleteCallback.cs | 125 ------------------ .../Model/ReferCallStatusEnum.cs | 19 --- 5 files changed, 234 deletions(-) delete mode 100644 docs/ReferCallStatusEnum.md delete mode 100644 docs/ReferCompleteCallback.md delete mode 100644 src/Bandwidth.Standard.Test/Unit/Model/ReferCompleteCallbackTests.cs delete mode 100644 src/Bandwidth.Standard/Model/Bxml/ReferCompleteCallback.cs delete mode 100644 src/Bandwidth.Standard/Model/ReferCallStatusEnum.cs diff --git a/docs/ReferCallStatusEnum.md b/docs/ReferCallStatusEnum.md deleted file mode 100644 index 6f190dc..0000000 --- a/docs/ReferCallStatusEnum.md +++ /dev/null @@ -1,8 +0,0 @@ -# Bandwidth.Standard.Model.ReferCallStatusEnum - -## Enum - -* `Success` (value: `success`) -* `Failure` (value: `failure`) - -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) \ No newline at end of file diff --git a/docs/ReferCompleteCallback.md b/docs/ReferCompleteCallback.md deleted file mode 100644 index 865e11c..0000000 --- a/docs/ReferCompleteCallback.md +++ /dev/null @@ -1,24 +0,0 @@ -# Bandwidth.Standard.Model.ReferCompleteCallback -This event is sent to the referCompleteUrl of the A-leg's verb when the REFER attempt completes. - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -**EventType** | **string** | The event type. Always `referComplete`. | [optional] -**EventTime** | **DateTime** | The approximate UTC date and time when the event was generated by the Bandwidth server. | [optional] -**AccountId** | **string** | The user account associated with the call. | [optional] -**ApplicationId** | **string** | The id of the application associated with the call. | [optional] -**From** | **string** | The provided identifier of the caller. | [optional] -**To** | **string** | The phone number that received the call. | [optional] -**Direction** | **CallDirectionEnum** | Call direction (`inbound`). | [optional] -**CallId** | **string** | The call id associated with the event. | [optional] -**CallUrl** | **string** | The URL of the call associated with the event. | [optional] -**StartTime** | **DateTime** | Time the call was started. | [optional] -**AnswerTime** | **DateTime** | Time the call was answered. | [optional] -**ReferCallStatus** | **ReferCallStatusEnum** | Whether REFER succeeded or failed. | [optional] -**Tag** | **string** | Optional custom string included in callbacks. | [optional] -**ReferSipResponseCode** | **int?** | Optional SIP response code from the REFER transaction. | [optional] -**NotifySipResponseCode** | **int?** | Optional SIP response code from the NOTIFY transaction. | [optional] - -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) \ No newline at end of file diff --git a/src/Bandwidth.Standard.Test/Unit/Model/ReferCompleteCallbackTests.cs b/src/Bandwidth.Standard.Test/Unit/Model/ReferCompleteCallbackTests.cs deleted file mode 100644 index bdfd4e2..0000000 --- a/src/Bandwidth.Standard.Test/Unit/Model/ReferCompleteCallbackTests.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Bandwidth.Standard.Model; -using Newtonsoft.Json; -using Xunit; - -namespace Bandwidth.Standard.Test.Unit.Model -{ - public class ReferCompleteCallbackTests - { - [Fact] - public void ReferCompleteSuccessTest() - { - var callback = Deserialize("{\"eventType\":\"referComplete\",\"eventTime\":\"2024-01-01T00:00:00.000Z\",\"accountId\":\"9900000\",\"applicationId\":\"04e88489-df02-4e34-a0ee-27a91849555f\",\"from\":\"+15555550100\",\"to\":\"+15555550101\",\"direction\":\"inbound\",\"callId\":\"c-123\",\"callUrl\":\"https://voice.bandwidth.com/api/v2/accounts/9900000/calls/c-123\",\"startTime\":\"2024-01-01T00:00:00.000Z\",\"answerTime\":\"2024-01-01T00:00:01.000Z\",\"referCallStatus\":\"success\"}"); - - Assert.Equal(ReferCallStatusEnum.Success, callback.ReferCallStatus); - Assert.Null(callback.ReferSipResponseCode); - Assert.Null(callback.NotifySipResponseCode); - } - - [Fact] - public void ReferCompleteReferRejectedTest() - { - var callback = Deserialize("{\"eventType\":\"referComplete\",\"eventTime\":\"2024-01-01T00:00:00.000Z\",\"accountId\":\"9900000\",\"applicationId\":\"04e88489-df02-4e34-a0ee-27a91849555f\",\"from\":\"+15555550100\",\"to\":\"+15555550101\",\"direction\":\"inbound\",\"callId\":\"c-123\",\"callUrl\":\"https://voice.bandwidth.com/api/v2/accounts/9900000/calls/c-123\",\"startTime\":\"2024-01-01T00:00:00.000Z\",\"answerTime\":\"2024-01-01T00:00:01.000Z\",\"referCallStatus\":\"failure\",\"referSipResponseCode\":405}"); - - Assert.Equal(ReferCallStatusEnum.Failure, callback.ReferCallStatus); - Assert.Equal(405, callback.ReferSipResponseCode); - Assert.Null(callback.NotifySipResponseCode); - } - - [Fact] - public void ReferCompleteDestinationUnreachableTest() - { - var callback = Deserialize("{\"eventType\":\"referComplete\",\"eventTime\":\"2024-01-01T00:00:00.000Z\",\"accountId\":\"9900000\",\"applicationId\":\"04e88489-df02-4e34-a0ee-27a91849555f\",\"from\":\"+15555550100\",\"to\":\"+15555550101\",\"direction\":\"inbound\",\"callId\":\"c-123\",\"callUrl\":\"https://voice.bandwidth.com/api/v2/accounts/9900000/calls/c-123\",\"startTime\":\"2024-01-01T00:00:00.000Z\",\"answerTime\":\"2024-01-01T00:00:01.000Z\",\"referCallStatus\":\"failure\",\"referSipResponseCode\":202,\"notifySipResponseCode\":486}"); - - Assert.Equal(ReferCallStatusEnum.Failure, callback.ReferCallStatus); - Assert.Equal(202, callback.ReferSipResponseCode); - Assert.Equal(486, callback.NotifySipResponseCode); - } - - [Fact] - public void ReferCompleteNotifyTimeoutTest() - { - var callback = Deserialize("{\"eventType\":\"referComplete\",\"eventTime\":\"2024-01-01T00:00:00.000Z\",\"accountId\":\"9900000\",\"applicationId\":\"04e88489-df02-4e34-a0ee-27a91849555f\",\"from\":\"+15555550100\",\"to\":\"+15555550101\",\"direction\":\"inbound\",\"callId\":\"c-123\",\"callUrl\":\"https://voice.bandwidth.com/api/v2/accounts/9900000/calls/c-123\",\"startTime\":\"2024-01-01T00:00:00.000Z\",\"answerTime\":\"2024-01-01T00:00:01.000Z\",\"referCallStatus\":\"failure\",\"referSipResponseCode\":202}"); - - Assert.Equal(ReferCallStatusEnum.Failure, callback.ReferCallStatus); - Assert.Equal(202, callback.ReferSipResponseCode); - Assert.Null(callback.NotifySipResponseCode); - } - - private static ReferCompleteCallback Deserialize(string json) - { - var callback = JsonConvert.DeserializeObject(json); - Assert.NotNull(callback); - Assert.Equal("referComplete", callback.EventType); - Assert.Equal(CallDirectionEnum.Inbound, callback.Direction); - return callback; - } - } -} \ No newline at end of file diff --git a/src/Bandwidth.Standard/Model/Bxml/ReferCompleteCallback.cs b/src/Bandwidth.Standard/Model/Bxml/ReferCompleteCallback.cs deleted file mode 100644 index ea0b105..0000000 --- a/src/Bandwidth.Standard/Model/Bxml/ReferCompleteCallback.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Runtime.Serialization; -using System.Text; - -namespace Bandwidth.Standard.Model -{ - /// This event is sent to the referCompleteUrl of the A-leg's <Refer> verb when the REFER attempt completes. - [DataContract(Name = "referCompleteCallback")] - public partial class ReferCompleteCallback : IValidatableObject - { - public ReferCompleteCallback( - string eventType = default(string), - DateTime eventTime = default(DateTime), - string accountId = default(string), - string applicationId = default(string), - string from = default(string), - string to = default(string), - CallDirectionEnum? direction = default(CallDirectionEnum?), - string callId = default(string), - string callUrl = default(string), - DateTime startTime = default(DateTime), - DateTime answerTime = default(DateTime), - ReferCallStatusEnum referCallStatus = default(ReferCallStatusEnum), - string tag = default(string), - int? referSipResponseCode = default(int?), - int? notifySipResponseCode = default(int?)) - { - EventType = eventType; - EventTime = eventTime; - AccountId = accountId; - ApplicationId = applicationId; - From = from; - To = to; - Direction = direction; - CallId = callId; - CallUrl = callUrl; - StartTime = startTime; - AnswerTime = answerTime; - ReferCallStatus = referCallStatus; - Tag = tag; - ReferSipResponseCode = referSipResponseCode; - NotifySipResponseCode = notifySipResponseCode; - } - - [DataMember(Name = "eventType", EmitDefaultValue = false)] - public string EventType { get; set; } - - [DataMember(Name = "eventTime", EmitDefaultValue = false)] - public DateTime EventTime { get; set; } - - [DataMember(Name = "accountId", EmitDefaultValue = false)] - public string AccountId { get; set; } - - [DataMember(Name = "applicationId", EmitDefaultValue = false)] - public string ApplicationId { get; set; } - - [DataMember(Name = "from", EmitDefaultValue = false)] - public string From { get; set; } - - [DataMember(Name = "to", EmitDefaultValue = false)] - public string To { get; set; } - - [DataMember(Name = "direction", EmitDefaultValue = false)] - public CallDirectionEnum? Direction { get; set; } - - [DataMember(Name = "callId", EmitDefaultValue = false)] - public string CallId { get; set; } - - [DataMember(Name = "callUrl", EmitDefaultValue = false)] - public string CallUrl { get; set; } - - [DataMember(Name = "startTime", EmitDefaultValue = false)] - public DateTime StartTime { get; set; } - - [DataMember(Name = "answerTime", EmitDefaultValue = false)] - public DateTime AnswerTime { get; set; } - - [DataMember(Name = "referCallStatus", EmitDefaultValue = false)] - public ReferCallStatusEnum ReferCallStatus { get; set; } - - [DataMember(Name = "tag", EmitDefaultValue = true)] - public string Tag { get; set; } - - [DataMember(Name = "referSipResponseCode", EmitDefaultValue = true)] - public int? ReferSipResponseCode { get; set; } - - [DataMember(Name = "notifySipResponseCode", EmitDefaultValue = true)] - public int? NotifySipResponseCode { get; set; } - - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append("class ReferCompleteCallback {\n"); - sb.Append(" EventType: ").Append(EventType).Append("\n"); - sb.Append(" EventTime: ").Append(EventTime).Append("\n"); - sb.Append(" AccountId: ").Append(AccountId).Append("\n"); - sb.Append(" ApplicationId: ").Append(ApplicationId).Append("\n"); - sb.Append(" From: ").Append(From).Append("\n"); - sb.Append(" To: ").Append(To).Append("\n"); - sb.Append(" Direction: ").Append(Direction).Append("\n"); - sb.Append(" CallId: ").Append(CallId).Append("\n"); - sb.Append(" CallUrl: ").Append(CallUrl).Append("\n"); - sb.Append(" StartTime: ").Append(StartTime).Append("\n"); - sb.Append(" AnswerTime: ").Append(AnswerTime).Append("\n"); - sb.Append(" ReferCallStatus: ").Append(ReferCallStatus).Append("\n"); - sb.Append(" Tag: ").Append(Tag).Append("\n"); - sb.Append(" ReferSipResponseCode: ").Append(ReferSipResponseCode).Append("\n"); - sb.Append(" NotifySipResponseCode: ").Append(NotifySipResponseCode).Append("\n"); - sb.Append("}\n"); - return sb.ToString(); - } - - public virtual string ToJson() - { - return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); - } - - IEnumerable IValidatableObject.Validate(ValidationContext validationContext) - { - yield break; - } - } -} \ No newline at end of file diff --git a/src/Bandwidth.Standard/Model/ReferCallStatusEnum.cs b/src/Bandwidth.Standard/Model/ReferCallStatusEnum.cs deleted file mode 100644 index ad80039..0000000 --- a/src/Bandwidth.Standard/Model/ReferCallStatusEnum.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Runtime.Serialization; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace Bandwidth.Standard.Model -{ - /// Result of a refer attempt. - [JsonConverter(typeof(StringEnumConverter))] - public enum ReferCallStatusEnum - { - /// Enum Success for value: success - [EnumMember(Value = "success")] - Success = 1, - - /// Enum Failure for value: failure - [EnumMember(Value = "failure")] - Failure = 2 - } -} \ No newline at end of file From ef31b2565b401c740ac60573ce978edccb703996 Mon Sep 17 00:00:00 2001 From: atelegu Date: Tue, 26 May 2026 17:42:21 +0530 Subject: [PATCH 3/6] VAPI-3163 --- .../Unit/Model/Bxml/TestRefer.cs | 24 ++++++++++++++++ .../Model/Bxml/Verbs/Refer.cs | 28 ++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/Bandwidth.Standard.Test/Unit/Model/Bxml/TestRefer.cs b/src/Bandwidth.Standard.Test/Unit/Model/Bxml/TestRefer.cs index 7380b5f..9064e42 100644 --- a/src/Bandwidth.Standard.Test/Unit/Model/Bxml/TestRefer.cs +++ b/src/Bandwidth.Standard.Test/Unit/Model/Bxml/TestRefer.cs @@ -42,5 +42,29 @@ public void ReferSipUriMustStartWithSipScheme() var refer = new Refer(); Assert.Throws(() => refer.WithSipUri("tel:+15551234567")); } + + [Fact] + public void ReferInvalidMethodThrows() + { + var refer = new Refer(); + Assert.Throws(() => refer.WithReferCompleteMethod("DELETE")); + } + + [Fact] + public void ReferWithSipUriObjectOverload() + { + var sipUri = new Refer.SipUri { Uri = "sip:alice@atlanta.example.com" }; + var refer = new Refer().WithSipUri(sipUri); + Assert.Equal("sip:alice@atlanta.example.com", refer.SipUriElement.Uri); + } + + [Fact] + public void ReferMinimalOnlySipUri() + { + var refer = new Refer().WithSipUri("sip:bob@biloxi.example.com"); + var bxml = new Response(refer).ToBXML(); + Assert.Contains("sip:bob@biloxi.example.com", bxml); + Assert.Contains("referCompleteMethod=\"POST\"", bxml); + } } } \ No newline at end of file diff --git a/src/Bandwidth.Standard/Model/Bxml/Verbs/Refer.cs b/src/Bandwidth.Standard/Model/Bxml/Verbs/Refer.cs index fd93825..a712af8 100644 --- a/src/Bandwidth.Standard/Model/Bxml/Verbs/Refer.cs +++ b/src/Bandwidth.Standard/Model/Bxml/Verbs/Refer.cs @@ -4,17 +4,23 @@ namespace Bandwidth.Standard.Model.Bxml.Verbs { + /// /// The Refer verb is used to hand off a call to a SIP endpoint. /// + /// public class Refer : IVerb { private string referCompleteMethod; + /// /// URL to receive the refer complete callback. + /// [XmlAttribute("referCompleteUrl")] public string ReferCompleteUrl { get; set; } - /// HTTP method to send the refer complete callback. + /// + /// HTTP method to send the refer complete callback. GET or POST. Default value is POST. + /// [XmlAttribute("referCompleteMethod")] public string ReferCompleteMethod { @@ -29,61 +35,81 @@ public string ReferCompleteMethod } } + /// /// Optional custom string to include in callbacks. + /// [XmlAttribute("tag")] public string Tag { get; set; } + /// /// SIP URI destination for the REFER. + /// [XmlElement("SipUri")] public SipUri SipUriElement { get; set; } + /// /// Initializes a new instance of the Refer class. + /// public Refer() { ReferCompleteMethod = "POST"; } + /// /// Sets the SIP URI destination from a string. + /// public Refer WithSipUri(string sipUri) { SipUriElement = new SipUri { Uri = sipUri }; return this; } + /// /// Sets the SIP URI destination from a SipUri object. + /// public Refer WithSipUri(SipUri sipUri) { SipUriElement = sipUri; return this; } + /// /// Sets referCompleteUrl. + /// public Refer WithReferCompleteUrl(string referCompleteUrl) { ReferCompleteUrl = referCompleteUrl; return this; } + /// /// Sets referCompleteMethod. + /// public Refer WithReferCompleteMethod(string referCompleteMethod) { ReferCompleteMethod = referCompleteMethod; return this; } + /// /// Sets tag. + /// public Refer WithTag(string tag) { Tag = tag; return this; } + /// /// BXML tag to represent a SIP URI for the refer verb. + /// public class SipUri : IVerb { private string _uri; + /// /// SIP URI to refer the call to (must start with sip:). + /// [XmlText] public string Uri { From 1c8546464a61a744fde73e7b1e1f27ee39a00c9c Mon Sep 17 00:00:00 2001 From: atelegu Date: Fri, 29 May 2026 16:20:16 +0530 Subject: [PATCH 4/6] VAPI-3163 --- README.md | 32 ++++-------------------- docs/Refer.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 docs/Refer.md diff --git a/README.md b/README.md index 4e27baa..3832c32 100644 --- a/README.md +++ b/README.md @@ -104,33 +104,6 @@ namespace Example } } } -``` - -## BXML `` example - -```csharp -using Bandwidth.Standard.Model.Bxml; -using Bandwidth.Standard.Model.Bxml.Verbs; - -var refer = new Refer() - .WithSipUri("sip:alice@atlanta.example.com") - .WithReferCompleteUrl("https://example.com/handleRefer") - .WithReferCompleteMethod("POST") - .WithTag("handoff-123"); - -var bxml = new Response(refer).ToBXML(); - -When a REFER succeeds, the remote SIP endpoint redirects away from Bandwidth and the call is terminated. Do not expect post-success BXML execution on that call leg. - -## `referComplete` failure recovery example - -```csharp -// Example callback handler pseudocode -if (callback.ReferCallStatus == ReferCallStatusEnum.Failure) -{ - // Recover only on failure (e.g. fallback flow, retry, alternate route) -} - ## Documentation for API Endpoints @@ -399,6 +372,11 @@ Class | Method | HTTP request | Description - [Model.WebhookSubscriptionsListBody](docs/WebhookSubscriptionsListBody.md) + +## Documentation for BXML Verbs + + - [Bxml.Verbs.Refer](docs/Refer.md) + ## Documentation for Authorization diff --git a/docs/Refer.md b/docs/Refer.md new file mode 100644 index 0000000..13a0446 --- /dev/null +++ b/docs/Refer.md @@ -0,0 +1,67 @@ +# Bandwidth.Standard.Model.Bxml.Verbs.Refer + +The `` verb is used to hand off a call to a SIP endpoint via a SIP REFER. The call is transferred to the specified SIP URI, and an optional callback is sent when the transfer completes. + +For more details, see the [Bandwidth BXML Refer documentation](https://dev.bandwidth.com/docs/voice/bxml/refer.html). + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ReferCompleteUrl** | **string** | URL to receive the `referComplete` callback when the REFER is finished. | [optional] +**ReferCompleteMethod** | **string** | HTTP method to use for the `referComplete` callback. Must be `GET` or `POST`. | [optional] [default to `POST`] +**Tag** | **string** | Optional custom string to include in callbacks. Max 4096 characters. | [optional] +**SipUriElement** | [**Refer.SipUri**](#sipuri-nested-class) | The SIP URI destination for the REFER. Must start with `sip:`. | + +## SipUri Nested Class + +The `` element specifies the destination SIP URI for the REFER. + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Uri** | **string** | The SIP URI to refer the call to. Must start with `sip:`. | + +## Methods + +Name | Description +------------ | ------------- +`WithSipUri(string sipUri)` | Sets the SIP URI destination from a string. Returns the `Refer` instance for chaining. +`WithSipUri(SipUri sipUri)` | Sets the SIP URI destination from a `SipUri` object. Returns the `Refer` instance for chaining. +`WithReferCompleteUrl(string referCompleteUrl)` | Sets the `referCompleteUrl` attribute. Returns the `Refer` instance for chaining. +`WithReferCompleteMethod(string referCompleteMethod)` | Sets the `referCompleteMethod` attribute (`GET` or `POST`). Returns the `Refer` instance for chaining. +`WithTag(string tag)` | Sets the `tag` attribute. Returns the `Refer` instance for chaining. + +## Example Usage + +```csharp +using Bandwidth.Standard.Model.Bxml; +using Bandwidth.Standard.Model.Bxml.Verbs; + +var refer = new Refer() + .WithSipUri("sip:alice@atlanta.example.com") + .WithReferCompleteUrl("https://example.com/handleRefer") + .WithReferCompleteMethod("POST") + .WithTag("refer-tag"); + +var response = new Response(refer); +Console.WriteLine(response.ToBXML()); +``` + +### Output BXML + +```xml + + + + sip:alice@atlanta.example.com + + +``` + +## Validation + +- `SipUri.Uri` must start with `sip:` (case-insensitive). An `ArgumentException` is thrown if the value does not match. +- `ReferCompleteMethod` must be either `GET` or `POST`. An `ArgumentException` is thrown for any other value. + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + From ca77566e474b79c88109f5de0a4273b3f754e56c Mon Sep 17 00:00:00 2001 From: atelegu Date: Fri, 29 May 2026 16:23:37 +0530 Subject: [PATCH 5/6] VAPI-3163 --- docs/Refer.md | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/docs/Refer.md b/docs/Refer.md index 13a0446..508c6ad 100644 --- a/docs/Refer.md +++ b/docs/Refer.md @@ -31,33 +31,6 @@ Name | Description `WithReferCompleteMethod(string referCompleteMethod)` | Sets the `referCompleteMethod` attribute (`GET` or `POST`). Returns the `Refer` instance for chaining. `WithTag(string tag)` | Sets the `tag` attribute. Returns the `Refer` instance for chaining. -## Example Usage - -```csharp -using Bandwidth.Standard.Model.Bxml; -using Bandwidth.Standard.Model.Bxml.Verbs; - -var refer = new Refer() - .WithSipUri("sip:alice@atlanta.example.com") - .WithReferCompleteUrl("https://example.com/handleRefer") - .WithReferCompleteMethod("POST") - .WithTag("refer-tag"); - -var response = new Response(refer); -Console.WriteLine(response.ToBXML()); -``` - -### Output BXML - -```xml - - - - sip:alice@atlanta.example.com - - -``` - ## Validation - `SipUri.Uri` must start with `sip:` (case-insensitive). An `ArgumentException` is thrown if the value does not match. From 84ed3e12e3a46ae279a6e7ea13001c34234b6596 Mon Sep 17 00:00:00 2001 From: atelegu Date: Mon, 15 Jun 2026 16:33:13 +0530 Subject: [PATCH 6/6] VAPI-3163 --- .openapi-generator/FILES | 2 + README.md | 1 + api/openapi.yaml | 105 +++++++ bandwidth.yml | 48 ++++ docs/ReferCompleteCallback.md | 27 ++ .../Model/ReferCompleteCallback.cs | 259 ++++++++++++++++++ 6 files changed, 442 insertions(+) create mode 100644 docs/ReferCompleteCallback.md create mode 100644 src/Bandwidth.Standard/Model/ReferCompleteCallback.cs diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index 6043157..fec913c 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -168,6 +168,7 @@ docs/RecordingTranscriptions.md docs/RecordingsApi.md docs/RedirectCallback.md docs/RedirectMethodEnum.md +docs/ReferCompleteCallback.md docs/SipConnectionMetadata.md docs/SipCredentials.md docs/SmsMessageContent.md @@ -403,6 +404,7 @@ src/Bandwidth.Standard/Model/RecordingTranscriptionMetadata.cs src/Bandwidth.Standard/Model/RecordingTranscriptions.cs src/Bandwidth.Standard/Model/RedirectCallback.cs src/Bandwidth.Standard/Model/RedirectMethodEnum.cs +src/Bandwidth.Standard/Model/ReferCompleteCallback.cs src/Bandwidth.Standard/Model/SipConnectionMetadata.cs src/Bandwidth.Standard/Model/SipCredentials.cs src/Bandwidth.Standard/Model/SmsMessageContent.cs diff --git a/README.md b/README.md index 3832c32..2b6b3a4 100644 --- a/README.md +++ b/README.md @@ -328,6 +328,7 @@ Class | Method | HTTP request | Description - [Model.RecordingTranscriptions](docs/RecordingTranscriptions.md) - [Model.RedirectCallback](docs/RedirectCallback.md) - [Model.RedirectMethodEnum](docs/RedirectMethodEnum.md) + - [Model.ReferCompleteCallback](docs/ReferCompleteCallback.md) - [Model.SipConnectionMetadata](docs/SipConnectionMetadata.md) - [Model.SipCredentials](docs/SipCredentials.md) - [Model.SmsMessageContent](docs/SmsMessageContent.md) diff --git a/api/openapi.yaml b/api/openapi.yaml index 77f3127..2a45b0c 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -13398,6 +13398,105 @@ components: example: "+15555555555" type: string type: object + referCompleteCallback: + description: "The Refer Complete event is fired when the verb finishes\ + \ executing. This is sent to the referCompleteUrl specified on the \ + \ verb, and the BXML returned in it is executed on the call." + properties: + eventType: + description: "The event type, value can be one of the following: answer,\ + \ bridgeComplete, bridgeTargetComplete, conferenceCreated, conferenceRedirect,\ + \ conferenceMemberJoin, conferenceMemberExit, conferenceCompleted, conferenceRecordingAvailable,\ + \ disconnect, dtmf, gather, initiate, machineDetectionComplete, recordingComplete,\ + \ recordingAvailable, redirect, transcriptionAvailable, transferAnswer,\ + \ transferComplete, transferDisconnect." + example: bridgeComplete + type: string + eventTime: + description: "The approximate UTC date and time when the event was generated\ + \ by the Bandwidth server, in ISO 8601 format. This may not be exactly\ + \ the time of event execution." + example: 2022-06-17T22:19:40.375Z + format: date-time + type: string + accountId: + description: The user account associated with the call. + example: "9900000" + type: string + applicationId: + description: The id of the application associated with the call. + example: 04e88489-df02-4e34-a0ee-27a91849555f + type: string + from: + description: The provided identifier of the caller. Must be a phone number + in E.164 format (e.g. +15555555555). + example: "+15555555555" + type: string + to: + description: "The phone number that received the call, in E.164 format (e.g.\ + \ +15555555555)." + example: "+15555555555" + type: string + direction: + $ref: '#/components/schemas/callDirectionEnum' + callId: + description: The call id associated with the event. + example: c-15ac29a2-1331029c-2cb0-4a07-b215-b22865662d85 + type: string + callUrl: + description: The URL of the call associated with the event. + example: https://voice.bandwidth.com/api/v2/accounts/9900000/calls/c-15ac29a2-1331029c-2cb0-4a07-b215-b22865662d85 + format: uri + type: string + enqueuedTime: + description: "(optional) If call queueing is enabled and this is an outbound\ + \ call, time the call was queued, in ISO 8601 format." + example: 2022-06-17T22:20:00Z + format: date-time + nullable: true + type: string + startTime: + description: "Time the call was started, in ISO 8601 format." + example: 2022-06-17T22:19:40.375Z + format: date-time + type: string + answerTime: + description: "Time the call was answered, in ISO 8601 format." + example: 2022-06-17T22:20:00Z + format: date-time + nullable: true + type: string + tag: + description: "(optional) The tag specified on call creation. If no tag was\ + \ specified or it was previously cleared, this field will not be present." + example: exampleTag + nullable: true + type: string + sipResponseCode: + description: "The SIP response code from the REFER request, indicating the\ + \ outcome of the operation (e.g., 200 for success, 404 for not found)." + example: 200 + nullable: true + type: integer + cause: + description: "Reason the call failed - hangup, busy, timeout, cancel, rejected,\ + \ callback-error, invalid-bxml, application-error, account-limit, node-capacity-exceeded,\ + \ error, or unknown." + example: busy + type: string + errorMessage: + description: Text explaining the reason that caused the call to fail in + case of errors. + example: Call c-2a913f94-6a486f3a-3cae-4034-bcc3-f0c9fa77ca2f is already + bridged with another call + nullable: true + type: string + errorId: + description: Bandwidth's internal id that references the error event. + example: 4642074b-7b58-478b-96e4-3a60955c6765 + nullable: true + type: string + type: object transcriptionAvailableCallback: description: The Transcription Available event is sent when the recording transcription is available to be downloaded. @@ -13981,6 +14080,12 @@ components: example: 4642074b-7b58-478b-96e4-3a60955c6765 nullable: true type: string + sipResponseCode: + description: "The SIP response code from the REFER request, indicating the outcome\ + \ of the operation (e.g., 200 for success, 404 for not found)." + example: 200 + nullable: true + type: integer machineDetectionResult: description: "(optional) if machine detection was requested in sync mode, the\ \ result will be specified here. Possible values are the same as the async\ diff --git a/bandwidth.yml b/bandwidth.yml index 84e00b3..69e2162 100644 --- a/bandwidth.yml +++ b/bandwidth.yml @@ -5034,6 +5034,47 @@ components: $ref: '#/components/schemas/transferCallerId' transferTo: $ref: '#/components/schemas/transferTo' + referCompleteCallback: + type: object + description: >- + The Refer Complete event is fired when the verb finishes + executing. This is sent to the referCompleteUrl specified on the + verb, and the BXML returned in it is executed on the call. + properties: + eventType: + $ref: '#/components/schemas/eventType' + eventTime: + $ref: '#/components/schemas/eventTime' + accountId: + $ref: '#/components/schemas/accountId' + applicationId: + $ref: '#/components/schemas/applicationId1' + from: + $ref: '#/components/schemas/from' + to: + $ref: '#/components/schemas/to' + direction: + $ref: '#/components/schemas/callDirectionEnum' + callId: + $ref: '#/components/schemas/callId' + callUrl: + $ref: '#/components/schemas/callUrl' + enqueuedTime: + $ref: '#/components/schemas/enqueuedTime' + startTime: + $ref: '#/components/schemas/startTime' + answerTime: + $ref: '#/components/schemas/answerTime' + tag: + $ref: '#/components/schemas/tag1' + sipResponseCode: + $ref: '#/components/schemas/sipResponseCode' + cause: + $ref: '#/components/schemas/cause' + errorMessage: + $ref: '#/components/schemas/errorMessage' + errorId: + $ref: '#/components/schemas/errorId' transcriptionAvailableCallback: type: object description: >- @@ -5400,6 +5441,13 @@ components: description: Bandwidth's internal id that references the error event. example: 4642074b-7b58-478b-96e4-3a60955c6765 nullable: true + sipResponseCode: + type: integer + description: >- + The SIP response code from the REFER request, indicating the outcome + of the operation (e.g., 200 for success, 404 for not found). + example: 200 + nullable: true machineDetectionResult: type: object description: >- diff --git a/docs/ReferCompleteCallback.md b/docs/ReferCompleteCallback.md new file mode 100644 index 0000000..51865ef --- /dev/null +++ b/docs/ReferCompleteCallback.md @@ -0,0 +1,27 @@ +# Bandwidth.Standard.Model.ReferCompleteCallback +The Refer Complete event is fired when the verb finishes executing. This is sent to the referCompleteUrl specified on the verb, and the BXML returned in it is executed on the call. + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**EventType** | **string** | The event type, value can be one of the following: answer, bridgeComplete, bridgeTargetComplete, conferenceCreated, conferenceRedirect, conferenceMemberJoin, conferenceMemberExit, conferenceCompleted, conferenceRecordingAvailable, disconnect, dtmf, gather, initiate, machineDetectionComplete, recordingComplete, recordingAvailable, redirect, transcriptionAvailable, transferAnswer, transferComplete, transferDisconnect. | [optional] +**EventTime** | **DateTime** | The approximate UTC date and time when the event was generated by the Bandwidth server, in ISO 8601 format. This may not be exactly the time of event execution. | [optional] +**AccountId** | **string** | The user account associated with the call. | [optional] +**ApplicationId** | **string** | The id of the application associated with the call. | [optional] +**From** | **string** | The provided identifier of the caller. Must be a phone number in E.164 format (e.g. +15555555555). | [optional] +**To** | **string** | The phone number that received the call, in E.164 format (e.g. +15555555555). | [optional] +**Direction** | **CallDirectionEnum** | | [optional] +**CallId** | **string** | The call id associated with the event. | [optional] +**CallUrl** | **string** | The URL of the call associated with the event. | [optional] +**EnqueuedTime** | **DateTime?** | (optional) If call queueing is enabled and this is an outbound call, time the call was queued, in ISO 8601 format. | [optional] +**StartTime** | **DateTime** | Time the call was started, in ISO 8601 format. | [optional] +**AnswerTime** | **DateTime?** | Time the call was answered, in ISO 8601 format. | [optional] +**Tag** | **string** | (optional) The tag specified on call creation. If no tag was specified or it was previously cleared, this field will not be present. | [optional] +**SipResponseCode** | **int?** | The SIP response code from the REFER request, indicating the outcome of the operation (e.g., 200 for success, 404 for not found). | [optional] +**Cause** | **string** | Reason the call failed - hangup, busy, timeout, cancel, rejected, callback-error, invalid-bxml, application-error, account-limit, node-capacity-exceeded, error, or unknown. | [optional] +**ErrorMessage** | **string** | Text explaining the reason that caused the call to fail in case of errors. | [optional] +**ErrorId** | **string** | Bandwidth's internal id that references the error event. | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + diff --git a/src/Bandwidth.Standard/Model/ReferCompleteCallback.cs b/src/Bandwidth.Standard/Model/ReferCompleteCallback.cs new file mode 100644 index 0000000..9ec1b9d --- /dev/null +++ b/src/Bandwidth.Standard/Model/ReferCompleteCallback.cs @@ -0,0 +1,259 @@ +/* + * Bandwidth + * + * Bandwidth's Communication APIs + * + * The version of the OpenAPI document: 1.0.0 + * Contact: letstalk@bandwidth.com + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using System.ComponentModel.DataAnnotations; +using OpenAPIDateConverter = Bandwidth.Standard.Client.OpenAPIDateConverter; + +namespace Bandwidth.Standard.Model +{ + /// + /// The Refer Complete event is fired when the <Refer> verb finishes executing. This is sent to the referCompleteUrl specified on the <Refer> verb, and the BXML returned in it is executed on the call. + /// + [DataContract(Name = "referCompleteCallback")] + public partial class ReferCompleteCallback : IValidatableObject + { + + /// + /// Gets or Sets Direction + /// + [DataMember(Name = "direction", EmitDefaultValue = false)] + public CallDirectionEnum? Direction { get; set; } + /// + /// Initializes a new instance of the class. + /// + /// The event type, value can be one of the following: answer, bridgeComplete, bridgeTargetComplete, conferenceCreated, conferenceRedirect, conferenceMemberJoin, conferenceMemberExit, conferenceCompleted, conferenceRecordingAvailable, disconnect, dtmf, gather, initiate, machineDetectionComplete, recordingComplete, recordingAvailable, redirect, transcriptionAvailable, transferAnswer, transferComplete, transferDisconnect.. + /// The approximate UTC date and time when the event was generated by the Bandwidth server, in ISO 8601 format. This may not be exactly the time of event execution.. + /// The user account associated with the call.. + /// The id of the application associated with the call.. + /// The provided identifier of the caller. Must be a phone number in E.164 format (e.g. +15555555555).. + /// The phone number that received the call, in E.164 format (e.g. +15555555555).. + /// direction. + /// The call id associated with the event.. + /// The URL of the call associated with the event.. + /// (optional) If call queueing is enabled and this is an outbound call, time the call was queued, in ISO 8601 format.. + /// Time the call was started, in ISO 8601 format.. + /// Time the call was answered, in ISO 8601 format.. + /// (optional) The tag specified on call creation. If no tag was specified or it was previously cleared, this field will not be present.. + /// The SIP response code from the REFER request, indicating the outcome of the operation (e.g., 200 for success, 404 for not found).. + /// Reason the call failed - hangup, busy, timeout, cancel, rejected, callback-error, invalid-bxml, application-error, account-limit, node-capacity-exceeded, error, or unknown.. + /// Text explaining the reason that caused the call to fail in case of errors.. + /// Bandwidth's internal id that references the error event.. + public ReferCompleteCallback(string eventType = default(string), DateTime eventTime = default(DateTime), string accountId = default(string), string applicationId = default(string), string from = default(string), string to = default(string), CallDirectionEnum? direction = default(CallDirectionEnum?), string callId = default(string), string callUrl = default(string), DateTime? enqueuedTime = default(DateTime?), DateTime startTime = default(DateTime), DateTime? answerTime = default(DateTime?), string tag = default(string), int? sipResponseCode = default(int?), string cause = default(string), string errorMessage = default(string), string errorId = default(string)) + { + this.EventType = eventType; + this.EventTime = eventTime; + this.AccountId = accountId; + this.ApplicationId = applicationId; + this.From = from; + this.To = to; + this.Direction = direction; + this.CallId = callId; + this.CallUrl = callUrl; + this.EnqueuedTime = enqueuedTime; + this.StartTime = startTime; + this.AnswerTime = answerTime; + this.Tag = tag; + this.SipResponseCode = sipResponseCode; + this.Cause = cause; + this.ErrorMessage = errorMessage; + this.ErrorId = errorId; + } + + /// + /// The event type, value can be one of the following: answer, bridgeComplete, bridgeTargetComplete, conferenceCreated, conferenceRedirect, conferenceMemberJoin, conferenceMemberExit, conferenceCompleted, conferenceRecordingAvailable, disconnect, dtmf, gather, initiate, machineDetectionComplete, recordingComplete, recordingAvailable, redirect, transcriptionAvailable, transferAnswer, transferComplete, transferDisconnect. + /// + /// The event type, value can be one of the following: answer, bridgeComplete, bridgeTargetComplete, conferenceCreated, conferenceRedirect, conferenceMemberJoin, conferenceMemberExit, conferenceCompleted, conferenceRecordingAvailable, disconnect, dtmf, gather, initiate, machineDetectionComplete, recordingComplete, recordingAvailable, redirect, transcriptionAvailable, transferAnswer, transferComplete, transferDisconnect. + /// bridgeComplete + [DataMember(Name = "eventType", EmitDefaultValue = false)] + public string EventType { get; set; } + + /// + /// The approximate UTC date and time when the event was generated by the Bandwidth server, in ISO 8601 format. This may not be exactly the time of event execution. + /// + /// The approximate UTC date and time when the event was generated by the Bandwidth server, in ISO 8601 format. This may not be exactly the time of event execution. + /// 2022-06-17T22:19:40.375Z + [DataMember(Name = "eventTime", EmitDefaultValue = false)] + public DateTime EventTime { get; set; } + + /// + /// The user account associated with the call. + /// + /// The user account associated with the call. + /// 9900000 + [DataMember(Name = "accountId", EmitDefaultValue = false)] + public string AccountId { get; set; } + + /// + /// The id of the application associated with the call. + /// + /// The id of the application associated with the call. + /// 04e88489-df02-4e34-a0ee-27a91849555f + [DataMember(Name = "applicationId", EmitDefaultValue = false)] + public string ApplicationId { get; set; } + + /// + /// The provided identifier of the caller. Must be a phone number in E.164 format (e.g. +15555555555). + /// + /// The provided identifier of the caller. Must be a phone number in E.164 format (e.g. +15555555555). + /// +15555555555 + [DataMember(Name = "from", EmitDefaultValue = false)] + public string From { get; set; } + + /// + /// The phone number that received the call, in E.164 format (e.g. +15555555555). + /// + /// The phone number that received the call, in E.164 format (e.g. +15555555555). + /// +15555555555 + [DataMember(Name = "to", EmitDefaultValue = false)] + public string To { get; set; } + + /// + /// The call id associated with the event. + /// + /// The call id associated with the event. + /// c-15ac29a2-1331029c-2cb0-4a07-b215-b22865662d85 + [DataMember(Name = "callId", EmitDefaultValue = false)] + public string CallId { get; set; } + + /// + /// The URL of the call associated with the event. + /// + /// The URL of the call associated with the event. + /// https://voice.bandwidth.com/api/v2/accounts/9900000/calls/c-15ac29a2-1331029c-2cb0-4a07-b215-b22865662d85 + [DataMember(Name = "callUrl", EmitDefaultValue = false)] + public string CallUrl { get; set; } + + /// + /// (optional) If call queueing is enabled and this is an outbound call, time the call was queued, in ISO 8601 format. + /// + /// (optional) If call queueing is enabled and this is an outbound call, time the call was queued, in ISO 8601 format. + /// 2022-06-17T22:20Z + [DataMember(Name = "enqueuedTime", EmitDefaultValue = true)] + public DateTime? EnqueuedTime { get; set; } + + /// + /// Time the call was started, in ISO 8601 format. + /// + /// Time the call was started, in ISO 8601 format. + /// 2022-06-17T22:19:40.375Z + [DataMember(Name = "startTime", EmitDefaultValue = false)] + public DateTime StartTime { get; set; } + + /// + /// Time the call was answered, in ISO 8601 format. + /// + /// Time the call was answered, in ISO 8601 format. + /// 2022-06-17T22:20Z + [DataMember(Name = "answerTime", EmitDefaultValue = true)] + public DateTime? AnswerTime { get; set; } + + /// + /// (optional) The tag specified on call creation. If no tag was specified or it was previously cleared, this field will not be present. + /// + /// (optional) The tag specified on call creation. If no tag was specified or it was previously cleared, this field will not be present. + /// exampleTag + [DataMember(Name = "tag", EmitDefaultValue = true)] + public string Tag { get; set; } + + /// + /// The SIP response code from the REFER request, indicating the outcome of the operation (e.g., 200 for success, 404 for not found). + /// + /// The SIP response code from the REFER request, indicating the outcome of the operation (e.g., 200 for success, 404 for not found). + /// 200 + [DataMember(Name = "sipResponseCode", EmitDefaultValue = true)] + public int? SipResponseCode { get; set; } + + /// + /// Reason the call failed - hangup, busy, timeout, cancel, rejected, callback-error, invalid-bxml, application-error, account-limit, node-capacity-exceeded, error, or unknown. + /// + /// Reason the call failed - hangup, busy, timeout, cancel, rejected, callback-error, invalid-bxml, application-error, account-limit, node-capacity-exceeded, error, or unknown. + /// busy + [DataMember(Name = "cause", EmitDefaultValue = false)] + public string Cause { get; set; } + + /// + /// Text explaining the reason that caused the call to fail in case of errors. + /// + /// Text explaining the reason that caused the call to fail in case of errors. + /// Call c-2a913f94-6a486f3a-3cae-4034-bcc3-f0c9fa77ca2f is already bridged with another call + [DataMember(Name = "errorMessage", EmitDefaultValue = true)] + public string ErrorMessage { get; set; } + + /// + /// Bandwidth's internal id that references the error event. + /// + /// Bandwidth's internal id that references the error event. + /// 4642074b-7b58-478b-96e4-3a60955c6765 + [DataMember(Name = "errorId", EmitDefaultValue = true)] + public string ErrorId { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class ReferCompleteCallback {\n"); + sb.Append(" EventType: ").Append(EventType).Append("\n"); + sb.Append(" EventTime: ").Append(EventTime).Append("\n"); + sb.Append(" AccountId: ").Append(AccountId).Append("\n"); + sb.Append(" ApplicationId: ").Append(ApplicationId).Append("\n"); + sb.Append(" From: ").Append(From).Append("\n"); + sb.Append(" To: ").Append(To).Append("\n"); + sb.Append(" Direction: ").Append(Direction).Append("\n"); + sb.Append(" CallId: ").Append(CallId).Append("\n"); + sb.Append(" CallUrl: ").Append(CallUrl).Append("\n"); + sb.Append(" EnqueuedTime: ").Append(EnqueuedTime).Append("\n"); + sb.Append(" StartTime: ").Append(StartTime).Append("\n"); + sb.Append(" AnswerTime: ").Append(AnswerTime).Append("\n"); + sb.Append(" Tag: ").Append(Tag).Append("\n"); + sb.Append(" SipResponseCode: ").Append(SipResponseCode).Append("\n"); + sb.Append(" Cause: ").Append(Cause).Append("\n"); + sb.Append(" ErrorMessage: ").Append(ErrorMessage).Append("\n"); + sb.Append(" ErrorId: ").Append(ErrorId).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + yield break; + } + } + +}