From 6e10fbd03b073c839ac09c6b4bf1343da3498cb1 Mon Sep 17 00:00:00 2001 From: DX-Bandwidth Date: Tue, 3 Nov 2026 14:09:08 +0000 Subject: [PATCH 1/3] Generate SDK with OpenAPI Generator Version 7.24.0 --- .openapi-generator/FILES | 2 + README.md | 1 + api/openapi.yaml | 523 +++++++++++++----- bandwidth.yml | 249 ++++++++- docs/DisconnectCallback.md | 4 +- docs/InboundCallbackMessage.md | 1 + docs/InitiateCallback.md | 2 +- docs/MultiChannelAction.md | 2 +- docs/MultiChannelActionCalendarEvent.md | 2 +- docs/RbmActionBase.md | 2 +- docs/RbmActionDial.md | 2 +- docs/RbmActionOpenUrl.md | 2 +- docs/RbmActionViewLocation.md | 2 +- docs/RbmSession.md | 18 + docs/RbmSuggestionResponse.md | 4 +- docs/StatusCallbackMessage.md | 1 + docs/StatusCallbackTypeEnum.md | 2 + docs/TransferDisconnectCallback.md | 3 + src/main/java/com/bandwidth/sdk/JSON.java | 2 + .../com/bandwidth/sdk/model/Callback.java | 6 +- .../sdk/model/DisconnectCallback.java | 73 ++- .../sdk/model/InboundCallbackMessage.java | 35 +- .../bandwidth/sdk/model/InitiateCallback.java | 2 +- .../MultiChannelActionCalendarEvent.java | 17 +- .../bandwidth/sdk/model/RbmActionBase.java | 17 +- .../bandwidth/sdk/model/RbmActionDial.java | 17 +- .../bandwidth/sdk/model/RbmActionOpenUrl.java | 17 +- .../sdk/model/RbmActionViewLocation.java | 17 +- .../com/bandwidth/sdk/model/RbmSession.java | 410 ++++++++++++++ .../sdk/model/RbmSuggestionResponse.java | 19 +- .../sdk/model/StatusCallbackMessage.java | 37 +- .../sdk/model/StatusCallbackTypeEnum.java | 6 +- .../sdk/model/TransferDisconnectCallback.java | 97 +++- 33 files changed, 1372 insertions(+), 222 deletions(-) create mode 100644 docs/RbmSession.md create mode 100644 src/main/java/com/bandwidth/sdk/model/RbmSession.java diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index 60258aad..3dc9bc83 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -157,6 +157,7 @@ docs/RbmMessageContentRichCard.md docs/RbmMessageContentText.md docs/RbmMessageMedia.md docs/RbmOpenUrlEnum.md +docs/RbmSession.md docs/RbmStandaloneCard.md docs/RbmSuggestionResponse.md docs/RbmWebViewEnum.md @@ -404,6 +405,7 @@ src/main/java/com/bandwidth/sdk/model/RbmMessageContentRichCard.java src/main/java/com/bandwidth/sdk/model/RbmMessageContentText.java src/main/java/com/bandwidth/sdk/model/RbmMessageMedia.java src/main/java/com/bandwidth/sdk/model/RbmOpenUrlEnum.java +src/main/java/com/bandwidth/sdk/model/RbmSession.java src/main/java/com/bandwidth/sdk/model/RbmStandaloneCard.java src/main/java/com/bandwidth/sdk/model/RbmSuggestionResponse.java src/main/java/com/bandwidth/sdk/model/RbmWebViewEnum.java diff --git a/README.md b/README.md index 2cdd9057..989ec367 100644 --- a/README.md +++ b/README.md @@ -334,6 +334,7 @@ Class | Method | HTTP request | Description - [RbmMessageContentText](docs/RbmMessageContentText.md) - [RbmMessageMedia](docs/RbmMessageMedia.md) - [RbmOpenUrlEnum](docs/RbmOpenUrlEnum.md) + - [RbmSession](docs/RbmSession.md) - [RbmStandaloneCard](docs/RbmStandaloneCard.md) - [RbmSuggestionResponse](docs/RbmSuggestionResponse.md) - [RbmWebViewEnum](docs/RbmWebViewEnum.md) diff --git a/api/openapi.yaml b/api/openapi.yaml index 01724894..5e978c1f 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -6536,6 +6536,8 @@ components: $ref: "#/components/examples/smsMessageReceivedCallbackExample" mmsMessageReceivedCallback: $ref: "#/components/examples/mmsMessageReceivedCallbackExample" + rbmMessageReceivedSessionCallback: + $ref: "#/components/examples/rbmMessageReceivedSessionCallbackExample" schema: $ref: "#/components/schemas/inboundCallback" description: |- @@ -6568,15 +6570,22 @@ components: $ref: "#/components/examples/mmsMessageDeliveredCallbackExample" groupMmsMessageDeliveredCallback: $ref: "#/components/examples/groupMmsMessageDeliveredCallbackExample" + rbmMessageDeliveredSessionCallback: + $ref: "#/components/examples/rbmMessageDeliveredSessionCallbackExample" + rbmMessageDeliveredCanInitiateSessionCallback: + $ref: "#/components/examples/rbmMessageDeliveredCanInitiateSessionCallbackExample" messageFailedCallback: $ref: "#/components/examples/messageFailedCallbackExample" + sessionStartedCallback: + $ref: "#/components/examples/sessionStartedCallbackExample" schema: $ref: "#/components/schemas/statusCallback" description: |-

This Outbound Message Webhook is an envelope containing status information regarding a message sent (MT) from your message-enabled Bandwidth telephone number. -

The payload type will be one of message-sending, message-sent, message-delivered, message-failed or message-read. -

Note that message-read callbacks are pertinent only for RBM messages sent from the /messages/multiChannel endpoint. +

The payload type will be one of message-sending, message-sent, message-delivered, message-failed, message-read or session-started. +

Note that message-read and session-started callbacks are pertinent only for RBM messages sent from the /messages/multiChannel endpoint. +

Note that session-started callbacks are pertinent only for RBM messages of agents with the Conversational billing category.

Please visit Webhooks

required: true responses: @@ -6734,6 +6743,30 @@ components: text: "Hey, check out the MMS!" media: - https://messaging.bandwidth.com/api/v2/users/9900902/media/14762070468292kw2fuqty55yp2b2/0/bw.png + rbmMessageReceivedSessionCallbackExample: + summary: An example of a rbm message-received callback body for a message that + is part of an RCS interactive session. + value: + time: 2026-08-06T10:00:05.502180Z + type: message-received + to: BandwidthRBM + description: Incoming message received + message: + id: 1786010405502l2ntaoajuqjhqnxu + owner: BandwidthRBM + applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 + time: 2026-08-06T10:00:05.302180Z + segmentCount: 1 + direction: in + to: + - BandwidthRBM + from: "+12345678902" + channel: RBM + content: + text: "Yes, please book it for tomorrow." + session: + canInitiate: false + id: 0f5a3b9c-2d4e-4f6a-8b1c-7e9d0a2b3c4d messageSendingCallbackExample: summary: An example of a message-sending callback body. value: @@ -6833,6 +6866,77 @@ components: owner: "+12345678902" direction: out segmentCount: 1 + rbmMessageDeliveredSessionCallbackExample: + summary: An example of a rbm message-delivered callback body for a message that + is part of an RCS interactive session. + value: + type: message-delivered + time: 2026-08-06T10:01:11.160744Z + description: Message delivered to handset. + to: "+12345678902" + message: + id: 1786010470868ty55yp2b2kw2fuq + time: 2026-08-06T10:01:10.868292Z + to: + - "+12345678902" + from: BandwidthRBM + text: "" + applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 + owner: BandwidthRBM + direction: out + segmentCount: 1 + channel: RBM + session: + canInitiate: false + id: 0f5a3b9c-2d4e-4f6a-8b1c-7e9d0a2b3c4d + rbmMessageDeliveredCanInitiateSessionCallbackExample: + summary: An example of a rbm message-delivered callback body for a message that + is not yet part of an RCS interactive session. + value: + type: message-delivered + time: 2026-08-06T09:59:56.160744Z + description: Message delivered to handset. + to: "+12345678902" + message: + id: 1786010395000kw2fuqty55yp2b2 + time: 2026-08-06T09:59:55.000000Z + to: + - "+12345678902" + from: BandwidthRBM + text: "" + applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 + owner: BandwidthRBM + direction: out + segmentCount: 1 + channel: RBM + session: + canInitiate: true + sessionStartedCallbackExample: + summary: An example of a session-started callback body. + value: + type: session-started + time: 2026-08-06T10:00:00.123000Z + description: Message is now part of an RCS interactive session. + to: "+12345678902" + message: + id: 1786010395000kw2fuqty55yp2b2 + owner: BandwidthRBM + applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 + time: 2026-08-06T10:00:00.120000Z + segmentCount: 1 + direction: out + to: + - "+12345678902" + from: BandwidthRBM + text: "" + tag: "" + channel: RBM + session: + canInitiate: false + id: 0f5a3b9c-2d4e-4f6a-8b1c-7e9d0a2b3c4d + type: INTERACTIVE_SESSION + startTime: 2026-08-06T09:59:55Z + endTime: 2026-08-07T09:59:55Z messageFailedCallbackExample: summary: An example of a message-failed callback body. value: @@ -9459,6 +9563,7 @@ components: messageLength: description: The length of the message content. example: 18 + nullable: true type: integer attachmentCount: description: The number of attachments the message has. @@ -9806,20 +9911,20 @@ components: text: Hello world suggestions: - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 owner: owner - from: BandwidthRBM applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 @@ -9828,20 +9933,20 @@ components: text: Hello world suggestions: - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 owner: owner - from: BandwidthRBM applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 @@ -9850,20 +9955,20 @@ components: text: Hello world suggestions: - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 owner: owner - from: BandwidthRBM applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 @@ -9872,20 +9977,20 @@ components: text: Hello world suggestions: - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 owner: owner tag: custom string priority: default @@ -10021,20 +10126,20 @@ components: text: Hello world suggestions: - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 properties: text: description: The text associated with the message. Must be 3270 characters @@ -10260,35 +10365,33 @@ components: type: string rbmActionText: description: Displayed text for user to click - example: Hello world + example: Track my order maxLength: 25 title: Text type: string rbmActionPostbackData: - description: Base64 payload the customer receives when the reply is clicked. - example: SGVsbG8gd29ybGQ= - format: byte + description: Payload the customer receives when the reply is clicked. + example: track-order-43654 maxLength: 2048 title: Post Back Data type: string rbmActionBase: example: type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 properties: type: $ref: "#/components/schemas/rbmActionTypeEnum" text: description: Displayed text for user to click - example: Hello world + example: Track my order maxLength: 25 title: Text type: string postbackData: - description: Base64 payload the customer receives when the reply is clicked. - example: SGVsbG8gd29ybGQ= - format: byte + description: Payload the customer receives when the reply is clicked. + example: track-order-43654 maxLength: 2048 title: Post Back Data type: string @@ -10466,20 +10569,20 @@ components: text: Hello world suggestions: - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 owner: owner multiChannelChannelListSMSResponseObject: allOf: @@ -10570,20 +10673,20 @@ components: text: Hello world suggestions: - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 owner: owner - from: BandwidthRBM applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 @@ -10592,20 +10695,20 @@ components: text: Hello world suggestions: - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 owner: owner - from: BandwidthRBM applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 @@ -10614,20 +10717,20 @@ components: text: Hello world suggestions: - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 owner: owner - from: BandwidthRBM applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 @@ -10636,20 +10739,20 @@ components: text: Hello world suggestions: - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 - type: REPLY - text: Hello world - postbackData: SGVsbG8gd29ybGQ= + text: Track my order + postbackData: track-order-43654 owner: owner tag: custom string priority: default @@ -10715,13 +10818,12 @@ components: rbmSuggestionResponse: properties: text: - description: The text associated with the suggestion response. - example: "Yes, I would like to proceed" + description: The text of the suggestion the user tapped. + example: Track my order type: string postbackData: - description: Base64 payload the customer receives when the reply is clicked. - example: SGVsbG8gd29ybGQ= - format: byte + description: Payload the customer receives when the reply is clicked. + example: track-order-43654 maxLength: 2048 title: Post Back Data type: string @@ -10744,6 +10846,53 @@ components: format: double type: string type: object + rbmSession: + description: |- + RCS interactive session information for the message. + An interactive session is a 24-hour window covering all Rich and Rich Media messages exchanged between an + RCS agent and a specific end user mobile number. It is triggered when at least 4 messages are exchanged within + 24 hours, at least 2 of them mobile-originated and at least 1 mobile-terminated. + Only present on `message-delivered`, `message-received` and `session-started` callbacks for RBM messages of + US agents with the Conversational billing category. Omitted for all other messages. + properties: + canInitiate: + description: |- + Whether the message can start an interactive session. + `false` if the message is already part of an active session, or if the agent is not eligible for + interactive session billing. + example: false + type: boolean + id: + description: |- + The unique identifier of the interactive session the message is part of. This is not a message ID. + Omitted if the message is not part of a session. + example: 0f5a3b9c-2d4e-4f6a-8b1c-7e9d0a2b3c4d + nullable: true + type: string + type: + description: |- + The type of the interactive session. + Only present on `session-started` callbacks. + example: INTERACTIVE_SESSION + nullable: true + type: string + startTime: + description: The time the 24-hour session window opened. Only present on + `session-started` callbacks. + example: 2026-08-06T09:59:55Z + format: date-time + nullable: true + type: string + endTime: + description: The time the 24-hour session window closes. Only present on + `session-started` callbacks. + example: 2026-08-07T09:59:55Z + format: date-time + nullable: true + type: string + required: + - canInitiate + type: object callback: description: |- Callbacks are divided into two types based on direction of the related message: @@ -10756,6 +10905,7 @@ components: message-delivered: "#/components/schemas/statusCallback" message-failed: "#/components/schemas/statusCallback" message-read: "#/components/schemas/statusCallback" + session-started: "#/components/schemas/statusCallback" message-received: "#/components/schemas/inboundCallback" requested-location-response: "#/components/schemas/inboundCallback" suggestion-response: "#/components/schemas/inboundCallback" @@ -10853,12 +11003,14 @@ components: - `message-delivered` indicates that the message was successfully delivered to handset. - `message-failed` indicates that the message could not be sent to the intended recipient. - `message-read` indicates that the RBM message was read by the recipient. + - `session-started` indicates that a previously exchanged RBM message is now part of an RCS interactive session and is no longer billed individually. enum: - message-sending - message-sent - message-delivered - message-failed - message-read + - session-started example: message-delivered type: string inboundCallbackTypeEnum: @@ -10936,6 +11088,8 @@ components: $ref: "#/components/schemas/priorityEnum" channel: $ref: "#/components/schemas/multiChannelMessageChannelEnum" + session: + $ref: "#/components/schemas/rbmSession" required: - applicationId - direction @@ -13041,11 +13195,44 @@ components: example: c95ac8d6e1a31c52eb38f419893c151633ec68f8d@sbc.bandwidth.com type: string sipResponseCode: - description: "(optional) The SIP status code returned by Bandwidth's SBC\ - \ when it rejected an outbound call's INVITE (e.g. 486 for busy, 603 for\ - \ decline). Present only when an outbound call was rejected by the SBC." + description: "(optional) The SIP status code of the final response that\ + \ rejected an outbound call's (or transferred leg's) INVITE (e.g. 486\ + \ for busy, 603 for decline). Present only when the call was rejected\ + \ with a SIP response." example: 486 type: integer + sipStatusLine: + description: "(optional) The full SIP status line, exactly as received,\ + \ of the final response that rejected an outbound call's INVITE. The reason\ + \ phrase can help distinguish outcomes that share a status code, such\ + \ as `603 Network Blocked` and `603 Decline`. Present only when an outbound\ + \ call was rejected with a SIP response." + example: SIP/2.0 603 Network Blocked + type: string + sipHeaders: + additionalProperties: + type: string + description: "(optional) Map of SIP headers, with lowercase keys (SIP headers\ + \ are case-insensitive). On the Initiate callback, contains the customer-supplied\ + \ X-* headers from the original INVITE; present only for inbound SIP URI\ + \ calls with custom headers. On the Disconnect and Transfer Disconnect\ + \ callbacks, contains a single `reason` key holding the raw, unmodified\ + \ `Reason` header value from the final SIP response that rejected an outbound\ + \ call (or transferred leg); present only when that response included\ + \ a `Reason` header (for example, `v=analytics1` call-analytics block\ + \ information from a terminating carrier). If the response carries more\ + \ than one `Reason` header, all values are returned in the order received,\ + \ separated by `, `. Note - on the Initiate callback, keys preserve the\ + \ original SIP header name in lowercase rather than Bandwidth's usual\ + \ camelCase JSON convention, since these are passthrough values from the\ + \ caller's SIP INVITE, not Bandwidth-defined fields. If the same header\ + \ name is sent more than once in the INVITE, only the last value is kept.\ + \ The example shown is for the Initiate callback; on the Disconnect and\ + \ Transfer Disconnect callbacks the only key is `reason`." + example: + x-custom-header: customer-value + x-session-id: sess-12345 + type: object type: object dtmfCallback: description: The DTMF event is sent for every digit detected after a @@ -13320,13 +13507,23 @@ components: sipHeaders: additionalProperties: type: string - description: "(optional) Map of customer-supplied X-* headers from the original\ - \ INVITE. Keys are lowercase (SIP headers are case-insensitive). Present\ - \ only for inbound SIP URI calls with custom headers. Note - keys preserve\ - \ the original SIP header name in lowercase rather than Bandwidth's usual\ + description: "(optional) Map of SIP headers, with lowercase keys (SIP headers\ + \ are case-insensitive). On the Initiate callback, contains the customer-supplied\ + \ X-* headers from the original INVITE; present only for inbound SIP URI\ + \ calls with custom headers. On the Disconnect and Transfer Disconnect\ + \ callbacks, contains a single `reason` key holding the raw, unmodified\ + \ `Reason` header value from the final SIP response that rejected an outbound\ + \ call (or transferred leg); present only when that response included\ + \ a `Reason` header (for example, `v=analytics1` call-analytics block\ + \ information from a terminating carrier). If the response carries more\ + \ than one `Reason` header, all values are returned in the order received,\ + \ separated by `, `. Note - on the Initiate callback, keys preserve the\ + \ original SIP header name in lowercase rather than Bandwidth's usual\ \ camelCase JSON convention, since these are passthrough values from the\ \ caller's SIP INVITE, not Bandwidth-defined fields. If the same header\ - \ name is sent more than once in the INVITE, only the last value is kept." + \ name is sent more than once in the INVITE, only the last value is kept.\ + \ The example shown is for the Initiate callback; on the Disconnect and\ + \ Transfer Disconnect callbacks the only key is `reason`." example: x-custom-header: customer-value x-session-id: sess-12345 @@ -14244,6 +14441,45 @@ components: example: 4642074b-7b58-478b-96e4-3a60955c6765 nullable: true type: string + sipResponseCode: + description: "(optional) The SIP status code of the final response that\ + \ rejected an outbound call's (or transferred leg's) INVITE (e.g. 486\ + \ for busy, 603 for decline). Present only when the call was rejected\ + \ with a SIP response." + example: 486 + type: integer + sipStatusLine: + description: "(optional) The full SIP status line, exactly as received,\ + \ of the final response that rejected an outbound call's INVITE. The reason\ + \ phrase can help distinguish outcomes that share a status code, such\ + \ as `603 Network Blocked` and `603 Decline`. Present only when an outbound\ + \ call was rejected with a SIP response." + example: SIP/2.0 603 Network Blocked + type: string + sipHeaders: + additionalProperties: + type: string + description: "(optional) Map of SIP headers, with lowercase keys (SIP headers\ + \ are case-insensitive). On the Initiate callback, contains the customer-supplied\ + \ X-* headers from the original INVITE; present only for inbound SIP URI\ + \ calls with custom headers. On the Disconnect and Transfer Disconnect\ + \ callbacks, contains a single `reason` key holding the raw, unmodified\ + \ `Reason` header value from the final SIP response that rejected an outbound\ + \ call (or transferred leg); present only when that response included\ + \ a `Reason` header (for example, `v=analytics1` call-analytics block\ + \ information from a terminating carrier). If the response carries more\ + \ than one `Reason` header, all values are returned in the order received,\ + \ separated by `, `. Note - on the Initiate callback, keys preserve the\ + \ original SIP header name in lowercase rather than Bandwidth's usual\ + \ camelCase JSON convention, since these are passthrough values from the\ + \ caller's SIP INVITE, not Bandwidth-defined fields. If the same header\ + \ name is sent more than once in the INVITE, only the last value is kept.\ + \ The example shown is for the Initiate callback; on the Disconnect and\ + \ Transfer Disconnect callbacks the only key is `reason`." + example: + x-custom-header: customer-value + x-session-id: sess-12345 + type: object type: object eventType: description: "The event type, value can be one of the following: answer, bridgeComplete,\ @@ -14526,23 +14762,40 @@ components: sipHeaders: additionalProperties: type: string - description: "(optional) Map of customer-supplied X-* headers from the original\ - \ INVITE. Keys are lowercase (SIP headers are case-insensitive). Present only\ - \ for inbound SIP URI calls with custom headers. Note - keys preserve the\ - \ original SIP header name in lowercase rather than Bandwidth's usual camelCase\ - \ JSON convention, since these are passthrough values from the caller's SIP\ - \ INVITE, not Bandwidth-defined fields. If the same header name is sent more\ - \ than once in the INVITE, only the last value is kept." + description: "(optional) Map of SIP headers, with lowercase keys (SIP headers\ + \ are case-insensitive). On the Initiate callback, contains the customer-supplied\ + \ X-* headers from the original INVITE; present only for inbound SIP URI calls\ + \ with custom headers. On the Disconnect and Transfer Disconnect callbacks,\ + \ contains a single `reason` key holding the raw, unmodified `Reason` header\ + \ value from the final SIP response that rejected an outbound call (or transferred\ + \ leg); present only when that response included a `Reason` header (for example,\ + \ `v=analytics1` call-analytics block information from a terminating carrier).\ + \ If the response carries more than one `Reason` header, all values are returned\ + \ in the order received, separated by `, `. Note - on the Initiate callback,\ + \ keys preserve the original SIP header name in lowercase rather than Bandwidth's\ + \ usual camelCase JSON convention, since these are passthrough values from\ + \ the caller's SIP INVITE, not Bandwidth-defined fields. If the same header\ + \ name is sent more than once in the INVITE, only the last value is kept.\ + \ The example shown is for the Initiate callback; on the Disconnect and Transfer\ + \ Disconnect callbacks the only key is `reason`." example: x-custom-header: customer-value x-session-id: sess-12345 type: object sipResponseCode: - description: "(optional) The SIP status code returned by Bandwidth's SBC when\ - \ it rejected an outbound call's INVITE (e.g. 486 for busy, 603 for decline).\ - \ Present only when an outbound call was rejected by the SBC." + description: "(optional) The SIP status code of the final response that rejected\ + \ an outbound call's (or transferred leg's) INVITE (e.g. 486 for busy, 603\ + \ for decline). Present only when the call was rejected with a SIP response." example: 486 type: integer + sipStatusLine: + description: "(optional) The full SIP status line, exactly as received, of the\ + \ final response that rejected an outbound call's INVITE. The reason phrase\ + \ can help distinguish outcomes that share a status code, such as `603 Network\ + \ Blocked` and `603 Decline`. Present only when an outbound call was rejected\ + \ with a SIP response." + example: SIP/2.0 603 Network Blocked + type: string codeRequest: properties: to: diff --git a/bandwidth.yml b/bandwidth.yml index 350b6217..0df9d764 100644 --- a/bandwidth.yml +++ b/bandwidth.yml @@ -2031,6 +2031,7 @@ components: messageLength: type: integer description: The length of the message content. + nullable: true example: 18 attachmentCount: type: integer @@ -2620,14 +2621,13 @@ components: type: string description: Displayed text for user to click maxLength: 25 - example: Hello world + example: Track my order rbmActionPostbackData: title: Post Back Data type: string - format: byte - description: Base64 payload the customer receives when the reply is clicked. + description: Payload the customer receives when the reply is clicked. maxLength: 2048 - example: SGVsbG8gd29ybGQ= + example: track-order-43654 rbmActionBase: type: object properties: @@ -2916,8 +2916,8 @@ components: properties: text: type: string - description: The text associated with the suggestion response. - example: Yes, I would like to proceed + description: The text of the suggestion the user tapped. + example: Track my order postbackData: $ref: '#/components/schemas/rbmActionPostbackData' pairedMessageId: @@ -2938,6 +2938,70 @@ components: format: double description: The longitude of the client's location. example: '-122.4194' + rbmSession: + type: object + description: >- + RCS interactive session information for the message. + + An interactive session is a 24-hour window covering all Rich and Rich + Media messages exchanged between an + + RCS agent and a specific end user mobile number. It is triggered when at + least 4 messages are exchanged within + + 24 hours, at least 2 of them mobile-originated and at least 1 + mobile-terminated. + + Only present on `message-delivered`, `message-received` and + `session-started` callbacks for RBM messages of + + US agents with the Conversational billing category. Omitted for all + other messages. + properties: + canInitiate: + type: boolean + description: >- + Whether the message can start an interactive session. + + `false` if the message is already part of an active session, or if + the agent is not eligible for + + interactive session billing. + example: false + id: + type: string + nullable: true + description: >- + The unique identifier of the interactive session the message is part + of. This is not a message ID. + + Omitted if the message is not part of a session. + example: 0f5a3b9c-2d4e-4f6a-8b1c-7e9d0a2b3c4d + type: + type: string + nullable: true + description: |- + The type of the interactive session. + Only present on `session-started` callbacks. + example: INTERACTIVE_SESSION + startTime: + type: string + nullable: true + format: date-time + description: >- + The time the 24-hour session window opened. Only present on + `session-started` callbacks. + example: '2026-08-06T09:59:55Z' + endTime: + type: string + nullable: true + format: date-time + description: >- + The time the 24-hour session window closes. Only present on + `session-started` callbacks. + example: '2026-08-07T09:59:55Z' + required: + - canInitiate callback: description: >- Callbacks are divided into two types based on direction of the related @@ -2960,6 +3024,7 @@ components: message-delivered: '#/components/schemas/statusCallback' message-failed: '#/components/schemas/statusCallback' message-read: '#/components/schemas/statusCallback' + session-started: '#/components/schemas/statusCallback' message-received: '#/components/schemas/inboundCallback' requested-location-response: '#/components/schemas/inboundCallback' suggestion-response: '#/components/schemas/inboundCallback' @@ -3060,12 +3125,17 @@ components: - `message-read` indicates that the RBM message was read by the recipient. + + - `session-started` indicates that a previously exchanged RBM message is + now part of an RCS interactive session and is no longer billed + individually. enum: - message-sending - message-sent - message-delivered - message-failed - message-read + - session-started example: message-delivered inboundCallbackTypeEnum: type: string @@ -3143,6 +3213,8 @@ components: $ref: '#/components/schemas/priorityEnum' channel: $ref: '#/components/schemas/multiChannelMessageChannelEnum' + session: + $ref: '#/components/schemas/rbmSession' required: - id - owner @@ -4876,6 +4948,10 @@ components: $ref: '#/components/schemas/sipCallId' sipResponseCode: $ref: '#/components/schemas/sipResponseCode' + sipStatusLine: + $ref: '#/components/schemas/sipStatusLine' + sipHeaders: + $ref: '#/components/schemas/sipHeaders' dtmfCallback: type: object description: >- @@ -5395,6 +5471,12 @@ components: $ref: '#/components/schemas/errorMessage' errorId: $ref: '#/components/schemas/errorId' + sipResponseCode: + $ref: '#/components/schemas/sipResponseCode' + sipStatusLine: + $ref: '#/components/schemas/sipStatusLine' + sipHeaders: + $ref: '#/components/schemas/sipHeaders' eventType: type: string description: >- @@ -5710,23 +5792,44 @@ components: additionalProperties: type: string description: >- - (optional) Map of customer-supplied X-* headers from the original - INVITE. Keys are lowercase (SIP headers are case-insensitive). Present - only for inbound SIP URI calls with custom headers. Note - keys preserve - the original SIP header name in lowercase rather than Bandwidth's usual - camelCase JSON convention, since these are passthrough values from the - caller's SIP INVITE, not Bandwidth-defined fields. If the same header - name is sent more than once in the INVITE, only the last value is kept. + (optional) Map of SIP headers, with lowercase keys (SIP headers are + case-insensitive). On the Initiate callback, contains the + customer-supplied X-* headers from the original INVITE; present only for + inbound SIP URI calls with custom headers. On the Disconnect and + Transfer Disconnect callbacks, contains a single `reason` key holding + the raw, unmodified `Reason` header value from the final SIP response + that rejected an outbound call (or transferred leg); present only when + that response included a `Reason` header (for example, `v=analytics1` + call-analytics block information from a terminating carrier). If the + response carries more than one `Reason` header, all values are returned + in the order received, separated by `, `. Note - on the Initiate + callback, keys preserve the original SIP header name in lowercase rather + than Bandwidth's usual camelCase JSON convention, since these are + passthrough values from the caller's SIP INVITE, not Bandwidth-defined + fields. If the same header name is sent more than once in the INVITE, + only the last value is kept. The example shown is for the Initiate + callback; on the Disconnect and Transfer Disconnect callbacks the only + key is `reason`. example: x-custom-header: customer-value x-session-id: sess-12345 sipResponseCode: type: integer description: >- - (optional) The SIP status code returned by Bandwidth's SBC when it - rejected an outbound call's INVITE (e.g. 486 for busy, 603 for decline). - Present only when an outbound call was rejected by the SBC. + (optional) The SIP status code of the final response that rejected an + outbound call's (or transferred leg's) INVITE (e.g. 486 for busy, 603 + for decline). Present only when the call was rejected with a SIP + response. example: 486 + sipStatusLine: + type: string + description: >- + (optional) The full SIP status line, exactly as received, of the final + response that rejected an outbound call's INVITE. The reason phrase can + help distinguish outcomes that share a status code, such as `603 Network + Blocked` and `603 Decline`. Present only when an outbound call was + rejected with a SIP response. + example: SIP/2.0 603 Network Blocked codeRequest: type: object properties: @@ -8878,6 +8981,31 @@ components: media: - >- https://messaging.bandwidth.com/api/v2/users/9900902/media/14762070468292kw2fuqty55yp2b2/0/bw.png + rbmMessageReceivedSessionCallbackExample: + summary: >- + An example of a rbm message-received callback body for a message that is + part of an RCS interactive session. + value: + time: '2026-08-06T10:00:05.502180Z' + type: message-received + to: BandwidthRBM + description: Incoming message received + message: + id: 1786010405502l2ntaoajuqjhqnxu + owner: BandwidthRBM + applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 + time: '2026-08-06T10:00:05.302180Z' + segmentCount: 1 + direction: in + to: + - BandwidthRBM + from: '+12345678902' + channel: RBM + content: + text: Yes, please book it for tomorrow. + session: + canInitiate: false + id: 0f5a3b9c-2d4e-4f6a-8b1c-7e9d0a2b3c4d messageSendingCallbackExample: summary: An example of a message-sending callback body. value: @@ -8977,6 +9105,79 @@ components: owner: '+12345678902' direction: out segmentCount: 1 + rbmMessageDeliveredSessionCallbackExample: + summary: >- + An example of a rbm message-delivered callback body for a message that + is part of an RCS interactive session. + value: + type: message-delivered + time: '2026-08-06T10:01:11.160744Z' + description: Message delivered to handset. + to: '+12345678902' + message: + id: 1786010470868ty55yp2b2kw2fuq + time: '2026-08-06T10:01:10.868292Z' + to: + - '+12345678902' + from: BandwidthRBM + text: '' + applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 + owner: BandwidthRBM + direction: out + segmentCount: 1 + channel: RBM + session: + canInitiate: false + id: 0f5a3b9c-2d4e-4f6a-8b1c-7e9d0a2b3c4d + rbmMessageDeliveredCanInitiateSessionCallbackExample: + summary: >- + An example of a rbm message-delivered callback body for a message that + is not yet part of an RCS interactive session. + value: + type: message-delivered + time: '2026-08-06T09:59:56.160744Z' + description: Message delivered to handset. + to: '+12345678902' + message: + id: 1786010395000kw2fuqty55yp2b2 + time: '2026-08-06T09:59:55.000000Z' + to: + - '+12345678902' + from: BandwidthRBM + text: '' + applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 + owner: BandwidthRBM + direction: out + segmentCount: 1 + channel: RBM + session: + canInitiate: true + sessionStartedCallbackExample: + summary: An example of a session-started callback body. + value: + type: session-started + time: '2026-08-06T10:00:00.123000Z' + description: Message is now part of an RCS interactive session. + to: '+12345678902' + message: + id: 1786010395000kw2fuqty55yp2b2 + owner: BandwidthRBM + applicationId: 93de2206-9669-4e07-948d-329f4b722ee2 + time: '2026-08-06T10:00:00.120000Z' + segmentCount: 1 + direction: out + to: + - '+12345678902' + from: BandwidthRBM + text: '' + tag: '' + channel: RBM + session: + canInitiate: false + id: 0f5a3b9c-2d4e-4f6a-8b1c-7e9d0a2b3c4d + type: INTERACTIVE_SESSION + startTime: '2026-08-06T09:59:55Z' + endTime: '2026-08-07T09:59:55Z' messageFailedCallbackExample: summary: An example of a message-failed callback body. value: @@ -9980,6 +10181,9 @@ components: $ref: '#/components/examples/smsMessageReceivedCallbackExample' mmsMessageReceivedCallback: $ref: '#/components/examples/mmsMessageReceivedCallbackExample' + rbmMessageReceivedSessionCallback: + $ref: >- + #/components/examples/rbmMessageReceivedSessionCallbackExample responses: '200': description: OK @@ -9995,8 +10199,9 @@ components: information regarding a message sent (MT) from your message-enabled Bandwidth telephone number. -

The payload type will be one of message-sending, message-sent, message-delivered, message-failed or message-read. -

Note that message-read callbacks are pertinent only for RBM messages sent from the /messages/multiChannel endpoint. +

The payload type will be one of message-sending, message-sent, message-delivered, message-failed, message-read or session-started. +

Note that message-read and session-started callbacks are pertinent only for RBM messages sent from the /messages/multiChannel endpoint. +

Note that session-started callbacks are pertinent only for RBM messages of agents with the Conversational billing category.

Please visit Webhooks

content: @@ -10015,8 +10220,16 @@ components: groupMmsMessageDeliveredCallback: $ref: >- #/components/examples/groupMmsMessageDeliveredCallbackExample + rbmMessageDeliveredSessionCallback: + $ref: >- + #/components/examples/rbmMessageDeliveredSessionCallbackExample + rbmMessageDeliveredCanInitiateSessionCallback: + $ref: >- + #/components/examples/rbmMessageDeliveredCanInitiateSessionCallbackExample messageFailedCallback: $ref: '#/components/examples/messageFailedCallbackExample' + sessionStartedCallback: + $ref: '#/components/examples/sessionStartedCallbackExample' responses: '200': description: OK diff --git a/docs/DisconnectCallback.md b/docs/DisconnectCallback.md index 132411f5..d1cb2aa8 100644 --- a/docs/DisconnectCallback.md +++ b/docs/DisconnectCallback.md @@ -26,7 +26,9 @@ The Disconnect event is fired when a call ends, for any reason. |**errorId** | **String** | Bandwidth's internal id that references the error event. | [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] | |**sipCallId** | **String** | (optional) The SIP Call-ID of the call's current SIP dialog with Bandwidth's SBC. Used to correlate dialogs and trace calls. Present on any call, inbound or outbound, once that dialog has been established; may be absent very early in a call before the dialog exists. | [optional] | -|**sipResponseCode** | **Integer** | (optional) The SIP status code returned by Bandwidth's SBC when it rejected an outbound call's INVITE (e.g. 486 for busy, 603 for decline). Present only when an outbound call was rejected by the SBC. | [optional] | +|**sipResponseCode** | **Integer** | (optional) The SIP status code of the final response that rejected an outbound call's (or transferred leg's) INVITE (e.g. 486 for busy, 603 for decline). Present only when the call was rejected with a SIP response. | [optional] | +|**sipStatusLine** | **String** | (optional) The full SIP status line, exactly as received, of the final response that rejected an outbound call's INVITE. The reason phrase can help distinguish outcomes that share a status code, such as `603 Network Blocked` and `603 Decline`. Present only when an outbound call was rejected with a SIP response. | [optional] | +|**sipHeaders** | **Map<String, String>** | (optional) Map of SIP headers, with lowercase keys (SIP headers are case-insensitive). On the Initiate callback, contains the customer-supplied X-* headers from the original INVITE; present only for inbound SIP URI calls with custom headers. On the Disconnect and Transfer Disconnect callbacks, contains a single `reason` key holding the raw, unmodified `Reason` header value from the final SIP response that rejected an outbound call (or transferred leg); present only when that response included a `Reason` header (for example, `v=analytics1` call-analytics block information from a terminating carrier). If the response carries more than one `Reason` header, all values are returned in the order received, separated by `, `. Note - on the Initiate callback, keys preserve the original SIP header name in lowercase rather than Bandwidth's usual camelCase JSON convention, since these are passthrough values from the caller's SIP INVITE, not Bandwidth-defined fields. If the same header name is sent more than once in the INVITE, only the last value is kept. The example shown is for the Initiate callback; on the Disconnect and Transfer Disconnect callbacks the only key is `reason`. | [optional] | diff --git a/docs/InboundCallbackMessage.md b/docs/InboundCallbackMessage.md index 2e3fd3d2..34cfef07 100644 --- a/docs/InboundCallbackMessage.md +++ b/docs/InboundCallbackMessage.md @@ -20,6 +20,7 @@ |**media** | **List<URI>** | Optional media, not applicable for sms | [optional] | |**priority** | **PriorityEnum** | | [optional] | |**channel** | **MultiChannelMessageChannelEnum** | | [optional] | +|**session** | [**RbmSession**](RbmSession.md) | | [optional] | |**content** | [**MultiChannelMessageContent**](MultiChannelMessageContent.md) | | [optional] | |**suggestionResponse** | [**RbmSuggestionResponse**](RbmSuggestionResponse.md) | | [optional] | |**locationResponse** | [**RbmLocationResponse**](RbmLocationResponse.md) | | [optional] | diff --git a/docs/InitiateCallback.md b/docs/InitiateCallback.md index c644cea2..70d4a974 100644 --- a/docs/InitiateCallback.md +++ b/docs/InitiateCallback.md @@ -22,7 +22,7 @@ The Initiate event is fired when an inbound call is received for a Telephone Num |**stirShaken** | [**StirShaken**](StirShaken.md) | | [optional] | |**uui** | **String** | The value of the `User-To-User` header to send within the initial `INVITE`. Must include the encoding parameter as specified in RFC 7433. Only `base64`, `jwt` and `hex` encoding are currently allowed. This value, including the encoding specifier, may not exceed 256 characters. | [optional] | |**sipCallId** | **String** | (optional) The SIP Call-ID of the call's current SIP dialog with Bandwidth's SBC. Used to correlate dialogs and trace calls. Present on any call, inbound or outbound, once that dialog has been established; may be absent very early in a call before the dialog exists. | [optional] | -|**sipHeaders** | **Map<String, String>** | (optional) Map of customer-supplied X-* headers from the original INVITE. Keys are lowercase (SIP headers are case-insensitive). Present only for inbound SIP URI calls with custom headers. Note - keys preserve the original SIP header name in lowercase rather than Bandwidth's usual camelCase JSON convention, since these are passthrough values from the caller's SIP INVITE, not Bandwidth-defined fields. If the same header name is sent more than once in the INVITE, only the last value is kept. | [optional] | +|**sipHeaders** | **Map<String, String>** | (optional) Map of SIP headers, with lowercase keys (SIP headers are case-insensitive). On the Initiate callback, contains the customer-supplied X-* headers from the original INVITE; present only for inbound SIP URI calls with custom headers. On the Disconnect and Transfer Disconnect callbacks, contains a single `reason` key holding the raw, unmodified `Reason` header value from the final SIP response that rejected an outbound call (or transferred leg); present only when that response included a `Reason` header (for example, `v=analytics1` call-analytics block information from a terminating carrier). If the response carries more than one `Reason` header, all values are returned in the order received, separated by `, `. Note - on the Initiate callback, keys preserve the original SIP header name in lowercase rather than Bandwidth's usual camelCase JSON convention, since these are passthrough values from the caller's SIP INVITE, not Bandwidth-defined fields. If the same header name is sent more than once in the INVITE, only the last value is kept. The example shown is for the Initiate callback; on the Disconnect and Transfer Disconnect callbacks the only key is `reason`. | [optional] | diff --git a/docs/MultiChannelAction.md b/docs/MultiChannelAction.md index 5722238b..5201b676 100644 --- a/docs/MultiChannelAction.md +++ b/docs/MultiChannelAction.md @@ -9,7 +9,7 @@ |------------ | ------------- | ------------- | -------------| |**type** | **RbmActionTypeEnum** | | | |**text** | **String** | Displayed text for user to click | | -|**postbackData** | **byte[]** | Base64 payload the customer receives when the reply is clicked. | | +|**postbackData** | **String** | Payload the customer receives when the reply is clicked. | | |**phoneNumber** | **String** | The phone number to dial. Must be E164 format. | | |**latitude** | **Double** | The latitude of the location. Must be in range [-90.000000, 90.000000]. | | |**longitude** | **Double** | The longitude of the location. Must be in range [-180.000000, 180.000000]. | | diff --git a/docs/MultiChannelActionCalendarEvent.md b/docs/MultiChannelActionCalendarEvent.md index f84cebfc..27d59ddc 100644 --- a/docs/MultiChannelActionCalendarEvent.md +++ b/docs/MultiChannelActionCalendarEvent.md @@ -9,7 +9,7 @@ |------------ | ------------- | ------------- | -------------| |**type** | **RbmActionTypeEnum** | | | |**text** | **String** | Displayed text for user to click | | -|**postbackData** | **byte[]** | Base64 payload the customer receives when the reply is clicked. | | +|**postbackData** | **String** | Payload the customer receives when the reply is clicked. | | |**title** | **String** | The title of the event. | | |**startTime** | **OffsetDateTime** | The start time of the event. Must be a valid RFC-3339 value, e.g., 2021-03-14T01:59:26Z or 2021-03-13T20:59:26-05:00. | | |**endTime** | **OffsetDateTime** | The end time of the event. Must be a valid RFC-3339 value, e.g., 2021-03-14T01:59:26Z or 2021-03-13T20:59:26-05:00. | | diff --git a/docs/RbmActionBase.md b/docs/RbmActionBase.md index 33aa0670..dca01d4d 100644 --- a/docs/RbmActionBase.md +++ b/docs/RbmActionBase.md @@ -9,7 +9,7 @@ |------------ | ------------- | ------------- | -------------| |**type** | **RbmActionTypeEnum** | | | |**text** | **String** | Displayed text for user to click | | -|**postbackData** | **byte[]** | Base64 payload the customer receives when the reply is clicked. | | +|**postbackData** | **String** | Payload the customer receives when the reply is clicked. | | diff --git a/docs/RbmActionDial.md b/docs/RbmActionDial.md index 617d607a..fea8bba8 100644 --- a/docs/RbmActionDial.md +++ b/docs/RbmActionDial.md @@ -9,7 +9,7 @@ |------------ | ------------- | ------------- | -------------| |**type** | **RbmActionTypeEnum** | | | |**text** | **String** | Displayed text for user to click | | -|**postbackData** | **byte[]** | Base64 payload the customer receives when the reply is clicked. | | +|**postbackData** | **String** | Payload the customer receives when the reply is clicked. | | |**phoneNumber** | **String** | The phone number to dial. Must be E164 format. | | diff --git a/docs/RbmActionOpenUrl.md b/docs/RbmActionOpenUrl.md index 8059c738..980a5983 100644 --- a/docs/RbmActionOpenUrl.md +++ b/docs/RbmActionOpenUrl.md @@ -9,7 +9,7 @@ |------------ | ------------- | ------------- | -------------| |**type** | **RbmActionTypeEnum** | | | |**text** | **String** | Displayed text for user to click | | -|**postbackData** | **byte[]** | Base64 payload the customer receives when the reply is clicked. | | +|**postbackData** | **String** | Payload the customer receives when the reply is clicked. | | |**url** | **URI** | The URL to open in browser. Must use http:// or https:// scheme. | | |**application** | **RbmOpenUrlEnum** | | [optional] | |**webviewViewMode** | **RbmWebViewEnum** | | [optional] | diff --git a/docs/RbmActionViewLocation.md b/docs/RbmActionViewLocation.md index 8e00e99d..9984e7eb 100644 --- a/docs/RbmActionViewLocation.md +++ b/docs/RbmActionViewLocation.md @@ -9,7 +9,7 @@ |------------ | ------------- | ------------- | -------------| |**type** | **RbmActionTypeEnum** | | | |**text** | **String** | Displayed text for user to click | | -|**postbackData** | **byte[]** | Base64 payload the customer receives when the reply is clicked. | | +|**postbackData** | **String** | Payload the customer receives when the reply is clicked. | | |**latitude** | **Double** | The latitude of the location. Must be in range [-90.000000, 90.000000]. | | |**longitude** | **Double** | The longitude of the location. Must be in range [-180.000000, 180.000000]. | | |**label** | **String** | The label of the location. | [optional] | diff --git a/docs/RbmSession.md b/docs/RbmSession.md new file mode 100644 index 00000000..0a465ed2 --- /dev/null +++ b/docs/RbmSession.md @@ -0,0 +1,18 @@ + + +# RbmSession + +RCS interactive session information for the message. An interactive session is a 24-hour window covering all Rich and Rich Media messages exchanged between an RCS agent and a specific end user mobile number. It is triggered when at least 4 messages are exchanged within 24 hours, at least 2 of them mobile-originated and at least 1 mobile-terminated. Only present on `message-delivered`, `message-received` and `session-started` callbacks for RBM messages of US agents with the Conversational billing category. Omitted for all other messages. + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**canInitiate** | **Boolean** | Whether the message can start an interactive session. `false` if the message is already part of an active session, or if the agent is not eligible for interactive session billing. | | +|**id** | **String** | The unique identifier of the interactive session the message is part of. This is not a message ID. Omitted if the message is not part of a session. | [optional] | +|**type** | **String** | The type of the interactive session. Only present on `session-started` callbacks. | [optional] | +|**startTime** | **OffsetDateTime** | The time the 24-hour session window opened. Only present on `session-started` callbacks. | [optional] | +|**endTime** | **OffsetDateTime** | The time the 24-hour session window closes. Only present on `session-started` callbacks. | [optional] | + + + diff --git a/docs/RbmSuggestionResponse.md b/docs/RbmSuggestionResponse.md index 39c8dd4f..31803394 100644 --- a/docs/RbmSuggestionResponse.md +++ b/docs/RbmSuggestionResponse.md @@ -7,8 +7,8 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| -|**text** | **String** | The text associated with the suggestion response. | [optional] | -|**postbackData** | **byte[]** | Base64 payload the customer receives when the reply is clicked. | [optional] | +|**text** | **String** | The text of the suggestion the user tapped. | [optional] | +|**postbackData** | **String** | Payload the customer receives when the reply is clicked. | [optional] | |**pairedMessageId** | **String** | Corresponding parent message ID (MT). | [optional] | diff --git a/docs/StatusCallbackMessage.md b/docs/StatusCallbackMessage.md index 532e5bd1..fb41f498 100644 --- a/docs/StatusCallbackMessage.md +++ b/docs/StatusCallbackMessage.md @@ -21,6 +21,7 @@ Message payload schema within a callback |**media** | **List<URI>** | Optional media, not applicable for sms | [optional] | |**priority** | **PriorityEnum** | | [optional] | |**channel** | **MultiChannelMessageChannelEnum** | | [optional] | +|**session** | [**RbmSession**](RbmSession.md) | | [optional] | diff --git a/docs/StatusCallbackTypeEnum.md b/docs/StatusCallbackTypeEnum.md index 5c74b1be..de54d4cb 100644 --- a/docs/StatusCallbackTypeEnum.md +++ b/docs/StatusCallbackTypeEnum.md @@ -15,5 +15,7 @@ * `MESSAGE_READ` (value: `"message-read"`) +* `SESSION_STARTED` (value: `"session-started"`) + diff --git a/docs/TransferDisconnectCallback.md b/docs/TransferDisconnectCallback.md index 3622add6..1810838d 100644 --- a/docs/TransferDisconnectCallback.md +++ b/docs/TransferDisconnectCallback.md @@ -28,6 +28,9 @@ This event is sent to the transferDisconnectUrl of each tag when i |**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] | +|**sipResponseCode** | **Integer** | (optional) The SIP status code of the final response that rejected an outbound call's (or transferred leg's) INVITE (e.g. 486 for busy, 603 for decline). Present only when the call was rejected with a SIP response. | [optional] | +|**sipStatusLine** | **String** | (optional) The full SIP status line, exactly as received, of the final response that rejected an outbound call's INVITE. The reason phrase can help distinguish outcomes that share a status code, such as `603 Network Blocked` and `603 Decline`. Present only when an outbound call was rejected with a SIP response. | [optional] | +|**sipHeaders** | **Map<String, String>** | (optional) Map of SIP headers, with lowercase keys (SIP headers are case-insensitive). On the Initiate callback, contains the customer-supplied X-* headers from the original INVITE; present only for inbound SIP URI calls with custom headers. On the Disconnect and Transfer Disconnect callbacks, contains a single `reason` key holding the raw, unmodified `Reason` header value from the final SIP response that rejected an outbound call (or transferred leg); present only when that response included a `Reason` header (for example, `v=analytics1` call-analytics block information from a terminating carrier). If the response carries more than one `Reason` header, all values are returned in the order received, separated by `, `. Note - on the Initiate callback, keys preserve the original SIP header name in lowercase rather than Bandwidth's usual camelCase JSON convention, since these are passthrough values from the caller's SIP INVITE, not Bandwidth-defined fields. If the same header name is sent more than once in the INVITE, only the last value is kept. The example shown is for the Initiate callback; on the Disconnect and Transfer Disconnect callbacks the only key is `reason`. | [optional] | diff --git a/src/main/java/com/bandwidth/sdk/JSON.java b/src/main/java/com/bandwidth/sdk/JSON.java index e40aa483..57852275 100644 --- a/src/main/java/com/bandwidth/sdk/JSON.java +++ b/src/main/java/com/bandwidth/sdk/JSON.java @@ -72,6 +72,7 @@ public Class getClassForElement(Json classByDiscriminatorValue.put("message-sending", com.bandwidth.sdk.model.StatusCallback.class); classByDiscriminatorValue.put("message-sent", com.bandwidth.sdk.model.StatusCallback.class); classByDiscriminatorValue.put("requested-location-response", com.bandwidth.sdk.model.InboundCallback.class); + classByDiscriminatorValue.put("session-started", com.bandwidth.sdk.model.StatusCallback.class); classByDiscriminatorValue.put("suggestion-response", com.bandwidth.sdk.model.InboundCallback.class); classByDiscriminatorValue.put("callback", com.bandwidth.sdk.model.Callback.class); return getClassByDiscriminator(classByDiscriminatorValue, @@ -266,6 +267,7 @@ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, Stri gsonBuilder.registerTypeAdapterFactory(new com.bandwidth.sdk.model.RbmMessageContentRichCard.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new com.bandwidth.sdk.model.RbmMessageContentText.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new com.bandwidth.sdk.model.RbmMessageMedia.CustomTypeAdapterFactory()); + gsonBuilder.registerTypeAdapterFactory(new com.bandwidth.sdk.model.RbmSession.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new com.bandwidth.sdk.model.RbmStandaloneCard.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new com.bandwidth.sdk.model.RbmSuggestionResponse.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new com.bandwidth.sdk.model.RecordingAvailableCallback.CustomTypeAdapterFactory()); diff --git a/src/main/java/com/bandwidth/sdk/model/Callback.java b/src/main/java/com/bandwidth/sdk/model/Callback.java index 1a7a7c50..7faf75e4 100644 --- a/src/main/java/com/bandwidth/sdk/model/Callback.java +++ b/src/main/java/com/bandwidth/sdk/model/Callback.java @@ -142,12 +142,16 @@ public Callback read(JsonReader in) throws IOException { deserialized = adapterInboundCallback.fromJsonTree(jsonObject); newCallback.setActualInstance(deserialized); return newCallback; + case "session-started": + deserialized = adapterStatusCallback.fromJsonTree(jsonObject); + newCallback.setActualInstance(deserialized); + return newCallback; case "suggestion-response": deserialized = adapterInboundCallback.fromJsonTree(jsonObject); newCallback.setActualInstance(deserialized); return newCallback; default: - log.log(Level.WARNING, String.format(java.util.Locale.ROOT, "Failed to lookup discriminator value `%s` for Callback. Possible values: message-delivered message-failed message-read message-received message-sending message-sent requested-location-response suggestion-response", jsonObject.get("type").getAsString())); + log.log(Level.WARNING, String.format(java.util.Locale.ROOT, "Failed to lookup discriminator value `%s` for Callback. Possible values: message-delivered message-failed message-read message-received message-sending message-sent requested-location-response session-started suggestion-response", jsonObject.get("type").getAsString())); } } diff --git a/src/main/java/com/bandwidth/sdk/model/DisconnectCallback.java b/src/main/java/com/bandwidth/sdk/model/DisconnectCallback.java index 31467393..8888d8bf 100644 --- a/src/main/java/com/bandwidth/sdk/model/DisconnectCallback.java +++ b/src/main/java/com/bandwidth/sdk/model/DisconnectCallback.java @@ -24,6 +24,8 @@ import java.net.URI; import java.time.OffsetDateTime; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import org.openapitools.jackson.nullable.JsonNullable; import com.google.gson.Gson; @@ -149,6 +151,16 @@ public class DisconnectCallback { @javax.annotation.Nullable private Integer sipResponseCode; + public static final String SERIALIZED_NAME_SIP_STATUS_LINE = "sipStatusLine"; + @SerializedName(SERIALIZED_NAME_SIP_STATUS_LINE) + @javax.annotation.Nullable + private String sipStatusLine; + + public static final String SERIALIZED_NAME_SIP_HEADERS = "sipHeaders"; + @SerializedName(SERIALIZED_NAME_SIP_HEADERS) + @javax.annotation.Nullable + private Map sipHeaders = new HashMap<>(); + public DisconnectCallback() { } @@ -500,7 +512,7 @@ public DisconnectCallback sipResponseCode(@javax.annotation.Nullable Integer sip } /** - * (optional) The SIP status code returned by Bandwidth's SBC when it rejected an outbound call's INVITE (e.g. 486 for busy, 603 for decline). Present only when an outbound call was rejected by the SBC. + * (optional) The SIP status code of the final response that rejected an outbound call's (or transferred leg's) INVITE (e.g. 486 for busy, 603 for decline). Present only when the call was rejected with a SIP response. * @return sipResponseCode */ @javax.annotation.Nullable @@ -512,6 +524,52 @@ public void setSipResponseCode(@javax.annotation.Nullable Integer sipResponseCod this.sipResponseCode = sipResponseCode; } + + public DisconnectCallback sipStatusLine(@javax.annotation.Nullable String sipStatusLine) { + this.sipStatusLine = sipStatusLine; + return this; + } + + /** + * (optional) The full SIP status line, exactly as received, of the final response that rejected an outbound call's INVITE. The reason phrase can help distinguish outcomes that share a status code, such as `603 Network Blocked` and `603 Decline`. Present only when an outbound call was rejected with a SIP response. + * @return sipStatusLine + */ + @javax.annotation.Nullable + public String getSipStatusLine() { + return sipStatusLine; + } + + public void setSipStatusLine(@javax.annotation.Nullable String sipStatusLine) { + this.sipStatusLine = sipStatusLine; + } + + + public DisconnectCallback sipHeaders(@javax.annotation.Nullable Map sipHeaders) { + this.sipHeaders = sipHeaders; + return this; + } + + public DisconnectCallback putSipHeadersItem(String key, String sipHeadersItem) { + if (this.sipHeaders == null) { + this.sipHeaders = new HashMap<>(); + } + this.sipHeaders.put(key, sipHeadersItem); + return this; + } + + /** + * (optional) Map of SIP headers, with lowercase keys (SIP headers are case-insensitive). On the Initiate callback, contains the customer-supplied X-* headers from the original INVITE; present only for inbound SIP URI calls with custom headers. On the Disconnect and Transfer Disconnect callbacks, contains a single `reason` key holding the raw, unmodified `Reason` header value from the final SIP response that rejected an outbound call (or transferred leg); present only when that response included a `Reason` header (for example, `v=analytics1` call-analytics block information from a terminating carrier). If the response carries more than one `Reason` header, all values are returned in the order received, separated by `, `. Note - on the Initiate callback, keys preserve the original SIP header name in lowercase rather than Bandwidth's usual camelCase JSON convention, since these are passthrough values from the caller's SIP INVITE, not Bandwidth-defined fields. If the same header name is sent more than once in the INVITE, only the last value is kept. The example shown is for the Initiate callback; on the Disconnect and Transfer Disconnect callbacks the only key is `reason`. + * @return sipHeaders + */ + @javax.annotation.Nullable + public Map getSipHeaders() { + return sipHeaders; + } + + public void setSipHeaders(@javax.annotation.Nullable Map sipHeaders) { + this.sipHeaders = sipHeaders; + } + /** * A container for additional, undeclared properties. * This is a holder for any undeclared properties as specified with @@ -585,7 +643,9 @@ public boolean equals(Object o) { Objects.equals(this.errorId, disconnectCallback.errorId) && Objects.equals(this.tag, disconnectCallback.tag) && Objects.equals(this.sipCallId, disconnectCallback.sipCallId) && - Objects.equals(this.sipResponseCode, disconnectCallback.sipResponseCode)&& + Objects.equals(this.sipResponseCode, disconnectCallback.sipResponseCode) && + Objects.equals(this.sipStatusLine, disconnectCallback.sipStatusLine) && + Objects.equals(this.sipHeaders, disconnectCallback.sipHeaders)&& Objects.equals(this.additionalProperties, disconnectCallback.additionalProperties); } @@ -595,7 +655,7 @@ private static boolean equalsNullable(JsonNullable a, JsonNullable b) @Override public int hashCode() { - return Objects.hash(eventType, eventTime, accountId, applicationId, from, to, callId, direction, callUrl, enqueuedTime, startTime, answerTime, endTime, cause, errorMessage, errorId, tag, sipCallId, sipResponseCode, additionalProperties); + return Objects.hash(eventType, eventTime, accountId, applicationId, from, to, callId, direction, callUrl, enqueuedTime, startTime, answerTime, endTime, cause, errorMessage, errorId, tag, sipCallId, sipResponseCode, sipStatusLine, sipHeaders, additionalProperties); } private static int hashCodeNullable(JsonNullable a) { @@ -628,6 +688,8 @@ public String toString() { sb.append(" tag: ").append(toIndentedString(tag)).append("\n"); sb.append(" sipCallId: ").append(toIndentedString(sipCallId)).append("\n"); sb.append(" sipResponseCode: ").append(toIndentedString(sipResponseCode)).append("\n"); + sb.append(" sipStatusLine: ").append(toIndentedString(sipStatusLine)).append("\n"); + sb.append(" sipHeaders: ").append(toIndentedString(sipHeaders)).append("\n"); sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); sb.append("}"); return sb.toString(); @@ -647,7 +709,7 @@ private String toIndentedString(Object o) { static { // a set of all properties/fields (JSON key names) - openapiFields = new HashSet(Arrays.asList("eventType", "eventTime", "accountId", "applicationId", "from", "to", "callId", "direction", "callUrl", "enqueuedTime", "startTime", "answerTime", "endTime", "cause", "errorMessage", "errorId", "tag", "sipCallId", "sipResponseCode")); + openapiFields = new HashSet(Arrays.asList("eventType", "eventTime", "accountId", "applicationId", "from", "to", "callId", "direction", "callUrl", "enqueuedTime", "startTime", "answerTime", "endTime", "cause", "errorMessage", "errorId", "tag", "sipCallId", "sipResponseCode", "sipStatusLine", "sipHeaders")); // a set of required properties/fields (JSON key names) openapiRequiredFields = new HashSet(0); @@ -706,6 +768,9 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti if ((jsonObj.get("sipCallId") != null && !jsonObj.get("sipCallId").isJsonNull()) && !jsonObj.get("sipCallId").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `sipCallId` to be a primitive type in the JSON string but got `%s`", jsonObj.get("sipCallId").toString())); } + if ((jsonObj.get("sipStatusLine") != null && !jsonObj.get("sipStatusLine").isJsonNull()) && !jsonObj.get("sipStatusLine").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `sipStatusLine` to be a primitive type in the JSON string but got `%s`", jsonObj.get("sipStatusLine").toString())); + } } public static class CustomTypeAdapterFactory implements TypeAdapterFactory { diff --git a/src/main/java/com/bandwidth/sdk/model/InboundCallbackMessage.java b/src/main/java/com/bandwidth/sdk/model/InboundCallbackMessage.java index 41225f1f..78514385 100644 --- a/src/main/java/com/bandwidth/sdk/model/InboundCallbackMessage.java +++ b/src/main/java/com/bandwidth/sdk/model/InboundCallbackMessage.java @@ -19,6 +19,7 @@ import com.bandwidth.sdk.model.MultiChannelMessageContent; import com.bandwidth.sdk.model.PriorityEnum; import com.bandwidth.sdk.model.RbmLocationResponse; +import com.bandwidth.sdk.model.RbmSession; import com.bandwidth.sdk.model.RbmSuggestionResponse; import com.google.gson.TypeAdapter; import com.google.gson.annotations.JsonAdapter; @@ -127,6 +128,11 @@ public class InboundCallbackMessage { @javax.annotation.Nullable private MultiChannelMessageChannelEnum channel; + public static final String SERIALIZED_NAME_SESSION = "session"; + @SerializedName(SERIALIZED_NAME_SESSION) + @javax.annotation.Nullable + private RbmSession session; + public static final String SERIALIZED_NAME_CONTENT = "content"; @SerializedName(SERIALIZED_NAME_CONTENT) @javax.annotation.Nullable @@ -408,6 +414,25 @@ public void setChannel(@javax.annotation.Nullable MultiChannelMessageChannelEnum } + public InboundCallbackMessage session(@javax.annotation.Nullable RbmSession session) { + this.session = session; + return this; + } + + /** + * Get session + * @return session + */ + @javax.annotation.Nullable + public RbmSession getSession() { + return session; + } + + public void setSession(@javax.annotation.Nullable RbmSession session) { + this.session = session; + } + + public InboundCallbackMessage content(@javax.annotation.Nullable MultiChannelMessageContent content) { this.content = content; return this; @@ -532,6 +557,7 @@ public boolean equals(Object o) { Objects.equals(this.media, inboundCallbackMessage.media) && Objects.equals(this.priority, inboundCallbackMessage.priority) && Objects.equals(this.channel, inboundCallbackMessage.channel) && + Objects.equals(this.session, inboundCallbackMessage.session) && Objects.equals(this.content, inboundCallbackMessage.content) && Objects.equals(this.suggestionResponse, inboundCallbackMessage.suggestionResponse) && Objects.equals(this.locationResponse, inboundCallbackMessage.locationResponse)&& @@ -540,7 +566,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(id, owner, applicationId, time, segmentCount, direction, to, from, text, tag, media, priority, channel, content, suggestionResponse, locationResponse, additionalProperties); + return Objects.hash(id, owner, applicationId, time, segmentCount, direction, to, from, text, tag, media, priority, channel, session, content, suggestionResponse, locationResponse, additionalProperties); } @Override @@ -560,6 +586,7 @@ public String toString() { sb.append(" media: ").append(toIndentedString(media)).append("\n"); sb.append(" priority: ").append(toIndentedString(priority)).append("\n"); sb.append(" channel: ").append(toIndentedString(channel)).append("\n"); + sb.append(" session: ").append(toIndentedString(session)).append("\n"); sb.append(" content: ").append(toIndentedString(content)).append("\n"); sb.append(" suggestionResponse: ").append(toIndentedString(suggestionResponse)).append("\n"); sb.append(" locationResponse: ").append(toIndentedString(locationResponse)).append("\n"); @@ -582,7 +609,7 @@ private String toIndentedString(Object o) { static { // a set of all properties/fields (JSON key names) - openapiFields = new HashSet(Arrays.asList("id", "owner", "applicationId", "time", "segmentCount", "direction", "to", "from", "text", "tag", "media", "priority", "channel", "content", "suggestionResponse", "locationResponse")); + openapiFields = new HashSet(Arrays.asList("id", "owner", "applicationId", "time", "segmentCount", "direction", "to", "from", "text", "tag", "media", "priority", "channel", "session", "content", "suggestionResponse", "locationResponse")); // a set of required properties/fields (JSON key names) openapiRequiredFields = new HashSet(Arrays.asList("id", "owner", "applicationId", "time", "segmentCount", "direction", "to", "from")); @@ -646,6 +673,10 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti if (jsonObj.get("channel") != null && !jsonObj.get("channel").isJsonNull()) { MultiChannelMessageChannelEnum.validateJsonElement(jsonObj.get("channel")); } + // validate the optional field `session` + if (jsonObj.get("session") != null && !jsonObj.get("session").isJsonNull()) { + RbmSession.validateJsonElement(jsonObj.get("session")); + } // validate the optional field `content` if (jsonObj.get("content") != null && !jsonObj.get("content").isJsonNull()) { MultiChannelMessageContent.validateJsonElement(jsonObj.get("content")); diff --git a/src/main/java/com/bandwidth/sdk/model/InitiateCallback.java b/src/main/java/com/bandwidth/sdk/model/InitiateCallback.java index df0cac18..6e4324d1 100644 --- a/src/main/java/com/bandwidth/sdk/model/InitiateCallback.java +++ b/src/main/java/com/bandwidth/sdk/model/InitiateCallback.java @@ -415,7 +415,7 @@ public InitiateCallback putSipHeadersItem(String key, String sipHeadersItem) { } /** - * (optional) Map of customer-supplied X-* headers from the original INVITE. Keys are lowercase (SIP headers are case-insensitive). Present only for inbound SIP URI calls with custom headers. Note - keys preserve the original SIP header name in lowercase rather than Bandwidth's usual camelCase JSON convention, since these are passthrough values from the caller's SIP INVITE, not Bandwidth-defined fields. If the same header name is sent more than once in the INVITE, only the last value is kept. + * (optional) Map of SIP headers, with lowercase keys (SIP headers are case-insensitive). On the Initiate callback, contains the customer-supplied X-* headers from the original INVITE; present only for inbound SIP URI calls with custom headers. On the Disconnect and Transfer Disconnect callbacks, contains a single `reason` key holding the raw, unmodified `Reason` header value from the final SIP response that rejected an outbound call (or transferred leg); present only when that response included a `Reason` header (for example, `v=analytics1` call-analytics block information from a terminating carrier). If the response carries more than one `Reason` header, all values are returned in the order received, separated by `, `. Note - on the Initiate callback, keys preserve the original SIP header name in lowercase rather than Bandwidth's usual camelCase JSON convention, since these are passthrough values from the caller's SIP INVITE, not Bandwidth-defined fields. If the same header name is sent more than once in the INVITE, only the last value is kept. The example shown is for the Initiate callback; on the Disconnect and Transfer Disconnect callbacks the only key is `reason`. * @return sipHeaders */ @javax.annotation.Nullable diff --git a/src/main/java/com/bandwidth/sdk/model/MultiChannelActionCalendarEvent.java b/src/main/java/com/bandwidth/sdk/model/MultiChannelActionCalendarEvent.java index 39a1355e..2d4387ab 100644 --- a/src/main/java/com/bandwidth/sdk/model/MultiChannelActionCalendarEvent.java +++ b/src/main/java/com/bandwidth/sdk/model/MultiChannelActionCalendarEvent.java @@ -65,7 +65,7 @@ public class MultiChannelActionCalendarEvent { public static final String SERIALIZED_NAME_POSTBACK_DATA = "postbackData"; @SerializedName(SERIALIZED_NAME_POSTBACK_DATA) @javax.annotation.Nonnull - private byte[] postbackData; + private String postbackData; public static final String SERIALIZED_NAME_TITLE = "title"; @SerializedName(SERIALIZED_NAME_TITLE) @@ -128,21 +128,21 @@ public void setText(@javax.annotation.Nonnull String text) { } - public MultiChannelActionCalendarEvent postbackData(@javax.annotation.Nonnull byte[] postbackData) { + public MultiChannelActionCalendarEvent postbackData(@javax.annotation.Nonnull String postbackData) { this.postbackData = postbackData; return this; } /** - * Base64 payload the customer receives when the reply is clicked. + * Payload the customer receives when the reply is clicked. * @return postbackData */ @javax.annotation.Nonnull - public byte[] getPostbackData() { + public String getPostbackData() { return postbackData; } - public void setPostbackData(@javax.annotation.Nonnull byte[] postbackData) { + public void setPostbackData(@javax.annotation.Nonnull String postbackData) { this.postbackData = postbackData; } @@ -279,7 +279,7 @@ public boolean equals(Object o) { MultiChannelActionCalendarEvent multiChannelActionCalendarEvent = (MultiChannelActionCalendarEvent) o; return Objects.equals(this.type, multiChannelActionCalendarEvent.type) && Objects.equals(this.text, multiChannelActionCalendarEvent.text) && - Arrays.equals(this.postbackData, multiChannelActionCalendarEvent.postbackData) && + Objects.equals(this.postbackData, multiChannelActionCalendarEvent.postbackData) && Objects.equals(this.title, multiChannelActionCalendarEvent.title) && Objects.equals(this.startTime, multiChannelActionCalendarEvent.startTime) && Objects.equals(this.endTime, multiChannelActionCalendarEvent.endTime) && @@ -289,7 +289,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(type, text, Arrays.hashCode(postbackData), title, startTime, endTime, description, additionalProperties); + return Objects.hash(type, text, postbackData, title, startTime, endTime, description, additionalProperties); } @Override @@ -353,6 +353,9 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti if (!jsonObj.get("text").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `text` to be a primitive type in the JSON string but got `%s`", jsonObj.get("text").toString())); } + if (!jsonObj.get("postbackData").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `postbackData` to be a primitive type in the JSON string but got `%s`", jsonObj.get("postbackData").toString())); + } if (!jsonObj.get("title").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `title` to be a primitive type in the JSON string but got `%s`", jsonObj.get("title").toString())); } diff --git a/src/main/java/com/bandwidth/sdk/model/RbmActionBase.java b/src/main/java/com/bandwidth/sdk/model/RbmActionBase.java index 41db7c12..96392ef5 100644 --- a/src/main/java/com/bandwidth/sdk/model/RbmActionBase.java +++ b/src/main/java/com/bandwidth/sdk/model/RbmActionBase.java @@ -64,7 +64,7 @@ public class RbmActionBase { public static final String SERIALIZED_NAME_POSTBACK_DATA = "postbackData"; @SerializedName(SERIALIZED_NAME_POSTBACK_DATA) @javax.annotation.Nonnull - private byte[] postbackData; + private String postbackData; public RbmActionBase() { } @@ -107,21 +107,21 @@ public void setText(@javax.annotation.Nonnull String text) { } - public RbmActionBase postbackData(@javax.annotation.Nonnull byte[] postbackData) { + public RbmActionBase postbackData(@javax.annotation.Nonnull String postbackData) { this.postbackData = postbackData; return this; } /** - * Base64 payload the customer receives when the reply is clicked. + * Payload the customer receives when the reply is clicked. * @return postbackData */ @javax.annotation.Nonnull - public byte[] getPostbackData() { + public String getPostbackData() { return postbackData; } - public void setPostbackData(@javax.annotation.Nonnull byte[] postbackData) { + public void setPostbackData(@javax.annotation.Nonnull String postbackData) { this.postbackData = postbackData; } @@ -182,13 +182,13 @@ public boolean equals(Object o) { RbmActionBase rbmActionBase = (RbmActionBase) o; return Objects.equals(this.type, rbmActionBase.type) && Objects.equals(this.text, rbmActionBase.text) && - Arrays.equals(this.postbackData, rbmActionBase.postbackData)&& + Objects.equals(this.postbackData, rbmActionBase.postbackData)&& Objects.equals(this.additionalProperties, rbmActionBase.additionalProperties); } @Override public int hashCode() { - return Objects.hash(type, text, Arrays.hashCode(postbackData), additionalProperties); + return Objects.hash(type, text, postbackData, additionalProperties); } @Override @@ -248,6 +248,9 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti if (!jsonObj.get("text").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `text` to be a primitive type in the JSON string but got `%s`", jsonObj.get("text").toString())); } + if (!jsonObj.get("postbackData").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `postbackData` to be a primitive type in the JSON string but got `%s`", jsonObj.get("postbackData").toString())); + } } public static class CustomTypeAdapterFactory implements TypeAdapterFactory { diff --git a/src/main/java/com/bandwidth/sdk/model/RbmActionDial.java b/src/main/java/com/bandwidth/sdk/model/RbmActionDial.java index feb7fa7e..d47bf2f0 100644 --- a/src/main/java/com/bandwidth/sdk/model/RbmActionDial.java +++ b/src/main/java/com/bandwidth/sdk/model/RbmActionDial.java @@ -64,7 +64,7 @@ public class RbmActionDial { public static final String SERIALIZED_NAME_POSTBACK_DATA = "postbackData"; @SerializedName(SERIALIZED_NAME_POSTBACK_DATA) @javax.annotation.Nonnull - private byte[] postbackData; + private String postbackData; public static final String SERIALIZED_NAME_PHONE_NUMBER = "phoneNumber"; @SerializedName(SERIALIZED_NAME_PHONE_NUMBER) @@ -112,21 +112,21 @@ public void setText(@javax.annotation.Nonnull String text) { } - public RbmActionDial postbackData(@javax.annotation.Nonnull byte[] postbackData) { + public RbmActionDial postbackData(@javax.annotation.Nonnull String postbackData) { this.postbackData = postbackData; return this; } /** - * Base64 payload the customer receives when the reply is clicked. + * Payload the customer receives when the reply is clicked. * @return postbackData */ @javax.annotation.Nonnull - public byte[] getPostbackData() { + public String getPostbackData() { return postbackData; } - public void setPostbackData(@javax.annotation.Nonnull byte[] postbackData) { + public void setPostbackData(@javax.annotation.Nonnull String postbackData) { this.postbackData = postbackData; } @@ -206,14 +206,14 @@ public boolean equals(Object o) { RbmActionDial rbmActionDial = (RbmActionDial) o; return Objects.equals(this.type, rbmActionDial.type) && Objects.equals(this.text, rbmActionDial.text) && - Arrays.equals(this.postbackData, rbmActionDial.postbackData) && + Objects.equals(this.postbackData, rbmActionDial.postbackData) && Objects.equals(this.phoneNumber, rbmActionDial.phoneNumber)&& Objects.equals(this.additionalProperties, rbmActionDial.additionalProperties); } @Override public int hashCode() { - return Objects.hash(type, text, Arrays.hashCode(postbackData), phoneNumber, additionalProperties); + return Objects.hash(type, text, postbackData, phoneNumber, additionalProperties); } @Override @@ -274,6 +274,9 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti if (!jsonObj.get("text").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `text` to be a primitive type in the JSON string but got `%s`", jsonObj.get("text").toString())); } + if (!jsonObj.get("postbackData").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `postbackData` to be a primitive type in the JSON string but got `%s`", jsonObj.get("postbackData").toString())); + } if (!jsonObj.get("phoneNumber").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `phoneNumber` to be a primitive type in the JSON string but got `%s`", jsonObj.get("phoneNumber").toString())); } diff --git a/src/main/java/com/bandwidth/sdk/model/RbmActionOpenUrl.java b/src/main/java/com/bandwidth/sdk/model/RbmActionOpenUrl.java index 654babe6..14f4bb55 100644 --- a/src/main/java/com/bandwidth/sdk/model/RbmActionOpenUrl.java +++ b/src/main/java/com/bandwidth/sdk/model/RbmActionOpenUrl.java @@ -67,7 +67,7 @@ public class RbmActionOpenUrl { public static final String SERIALIZED_NAME_POSTBACK_DATA = "postbackData"; @SerializedName(SERIALIZED_NAME_POSTBACK_DATA) @javax.annotation.Nonnull - private byte[] postbackData; + private String postbackData; public static final String SERIALIZED_NAME_URL = "url"; @SerializedName(SERIALIZED_NAME_URL) @@ -125,21 +125,21 @@ public void setText(@javax.annotation.Nonnull String text) { } - public RbmActionOpenUrl postbackData(@javax.annotation.Nonnull byte[] postbackData) { + public RbmActionOpenUrl postbackData(@javax.annotation.Nonnull String postbackData) { this.postbackData = postbackData; return this; } /** - * Base64 payload the customer receives when the reply is clicked. + * Payload the customer receives when the reply is clicked. * @return postbackData */ @javax.annotation.Nonnull - public byte[] getPostbackData() { + public String getPostbackData() { return postbackData; } - public void setPostbackData(@javax.annotation.Nonnull byte[] postbackData) { + public void setPostbackData(@javax.annotation.Nonnull String postbackData) { this.postbackData = postbackData; } @@ -257,7 +257,7 @@ public boolean equals(Object o) { RbmActionOpenUrl rbmActionOpenUrl = (RbmActionOpenUrl) o; return Objects.equals(this.type, rbmActionOpenUrl.type) && Objects.equals(this.text, rbmActionOpenUrl.text) && - Arrays.equals(this.postbackData, rbmActionOpenUrl.postbackData) && + Objects.equals(this.postbackData, rbmActionOpenUrl.postbackData) && Objects.equals(this.url, rbmActionOpenUrl.url) && Objects.equals(this.application, rbmActionOpenUrl.application) && Objects.equals(this.webviewViewMode, rbmActionOpenUrl.webviewViewMode)&& @@ -266,7 +266,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(type, text, Arrays.hashCode(postbackData), url, application, webviewViewMode, additionalProperties); + return Objects.hash(type, text, postbackData, url, application, webviewViewMode, additionalProperties); } @Override @@ -329,6 +329,9 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti if (!jsonObj.get("text").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `text` to be a primitive type in the JSON string but got `%s`", jsonObj.get("text").toString())); } + if (!jsonObj.get("postbackData").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `postbackData` to be a primitive type in the JSON string but got `%s`", jsonObj.get("postbackData").toString())); + } if (!jsonObj.get("url").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `url` to be a primitive type in the JSON string but got `%s`", jsonObj.get("url").toString())); } diff --git a/src/main/java/com/bandwidth/sdk/model/RbmActionViewLocation.java b/src/main/java/com/bandwidth/sdk/model/RbmActionViewLocation.java index 018d83c9..73f2a2fa 100644 --- a/src/main/java/com/bandwidth/sdk/model/RbmActionViewLocation.java +++ b/src/main/java/com/bandwidth/sdk/model/RbmActionViewLocation.java @@ -64,7 +64,7 @@ public class RbmActionViewLocation { public static final String SERIALIZED_NAME_POSTBACK_DATA = "postbackData"; @SerializedName(SERIALIZED_NAME_POSTBACK_DATA) @javax.annotation.Nonnull - private byte[] postbackData; + private String postbackData; public static final String SERIALIZED_NAME_LATITUDE = "latitude"; @SerializedName(SERIALIZED_NAME_LATITUDE) @@ -122,21 +122,21 @@ public void setText(@javax.annotation.Nonnull String text) { } - public RbmActionViewLocation postbackData(@javax.annotation.Nonnull byte[] postbackData) { + public RbmActionViewLocation postbackData(@javax.annotation.Nonnull String postbackData) { this.postbackData = postbackData; return this; } /** - * Base64 payload the customer receives when the reply is clicked. + * Payload the customer receives when the reply is clicked. * @return postbackData */ @javax.annotation.Nonnull - public byte[] getPostbackData() { + public String getPostbackData() { return postbackData; } - public void setPostbackData(@javax.annotation.Nonnull byte[] postbackData) { + public void setPostbackData(@javax.annotation.Nonnull String postbackData) { this.postbackData = postbackData; } @@ -254,7 +254,7 @@ public boolean equals(Object o) { RbmActionViewLocation rbmActionViewLocation = (RbmActionViewLocation) o; return Objects.equals(this.type, rbmActionViewLocation.type) && Objects.equals(this.text, rbmActionViewLocation.text) && - Arrays.equals(this.postbackData, rbmActionViewLocation.postbackData) && + Objects.equals(this.postbackData, rbmActionViewLocation.postbackData) && Objects.equals(this.latitude, rbmActionViewLocation.latitude) && Objects.equals(this.longitude, rbmActionViewLocation.longitude) && Objects.equals(this.label, rbmActionViewLocation.label)&& @@ -263,7 +263,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(type, text, Arrays.hashCode(postbackData), latitude, longitude, label, additionalProperties); + return Objects.hash(type, text, postbackData, latitude, longitude, label, additionalProperties); } @Override @@ -326,6 +326,9 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti if (!jsonObj.get("text").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `text` to be a primitive type in the JSON string but got `%s`", jsonObj.get("text").toString())); } + if (!jsonObj.get("postbackData").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `postbackData` to be a primitive type in the JSON string but got `%s`", jsonObj.get("postbackData").toString())); + } if (!jsonObj.get("latitude").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `latitude` to be a primitive type in the JSON string but got `%s`", jsonObj.get("latitude").toString())); } diff --git a/src/main/java/com/bandwidth/sdk/model/RbmSession.java b/src/main/java/com/bandwidth/sdk/model/RbmSession.java new file mode 100644 index 00000000..b810ae7d --- /dev/null +++ b/src/main/java/com/bandwidth/sdk/model/RbmSession.java @@ -0,0 +1,410 @@ +/* + * Bandwidth + * Bandwidth's Communication APIs + * + * The version of the OpenAPI document: 1.0.0 + * Contact: letstalk@bandwidth.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package com.bandwidth.sdk.model; + +import java.util.Objects; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.time.OffsetDateTime; +import java.util.Arrays; +import org.openapitools.jackson.nullable.JsonNullable; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.bandwidth.sdk.JSON; + +/** + * RCS interactive session information for the message. An interactive session is a 24-hour window covering all Rich and Rich Media messages exchanged between an RCS agent and a specific end user mobile number. It is triggered when at least 4 messages are exchanged within 24 hours, at least 2 of them mobile-originated and at least 1 mobile-terminated. Only present on `message-delivered`, `message-received` and `session-started` callbacks for RBM messages of US agents with the Conversational billing category. Omitted for all other messages. + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.24.0") +public class RbmSession { + public static final String SERIALIZED_NAME_CAN_INITIATE = "canInitiate"; + @SerializedName(SERIALIZED_NAME_CAN_INITIATE) + @javax.annotation.Nonnull + private Boolean canInitiate; + + public static final String SERIALIZED_NAME_ID = "id"; + @SerializedName(SERIALIZED_NAME_ID) + @javax.annotation.Nullable + private String id; + + public static final String SERIALIZED_NAME_TYPE = "type"; + @SerializedName(SERIALIZED_NAME_TYPE) + @javax.annotation.Nullable + private String type; + + public static final String SERIALIZED_NAME_START_TIME = "startTime"; + @SerializedName(SERIALIZED_NAME_START_TIME) + @javax.annotation.Nullable + private OffsetDateTime startTime; + + public static final String SERIALIZED_NAME_END_TIME = "endTime"; + @SerializedName(SERIALIZED_NAME_END_TIME) + @javax.annotation.Nullable + private OffsetDateTime endTime; + + public RbmSession() { + } + + public RbmSession canInitiate(@javax.annotation.Nonnull Boolean canInitiate) { + this.canInitiate = canInitiate; + return this; + } + + /** + * Whether the message can start an interactive session. `false` if the message is already part of an active session, or if the agent is not eligible for interactive session billing. + * @return canInitiate + */ + @javax.annotation.Nonnull + public Boolean getCanInitiate() { + return canInitiate; + } + + public void setCanInitiate(@javax.annotation.Nonnull Boolean canInitiate) { + this.canInitiate = canInitiate; + } + + + public RbmSession id(@javax.annotation.Nullable String id) { + this.id = id; + return this; + } + + /** + * The unique identifier of the interactive session the message is part of. This is not a message ID. Omitted if the message is not part of a session. + * @return id + */ + @javax.annotation.Nullable + public String getId() { + return id; + } + + public void setId(@javax.annotation.Nullable String id) { + this.id = id; + } + + + public RbmSession type(@javax.annotation.Nullable String type) { + this.type = type; + return this; + } + + /** + * The type of the interactive session. Only present on `session-started` callbacks. + * @return type + */ + @javax.annotation.Nullable + public String getType() { + return type; + } + + public void setType(@javax.annotation.Nullable String type) { + this.type = type; + } + + + public RbmSession startTime(@javax.annotation.Nullable OffsetDateTime startTime) { + this.startTime = startTime; + return this; + } + + /** + * The time the 24-hour session window opened. Only present on `session-started` callbacks. + * @return startTime + */ + @javax.annotation.Nullable + public OffsetDateTime getStartTime() { + return startTime; + } + + public void setStartTime(@javax.annotation.Nullable OffsetDateTime startTime) { + this.startTime = startTime; + } + + + public RbmSession endTime(@javax.annotation.Nullable OffsetDateTime endTime) { + this.endTime = endTime; + return this; + } + + /** + * The time the 24-hour session window closes. Only present on `session-started` callbacks. + * @return endTime + */ + @javax.annotation.Nullable + public OffsetDateTime getEndTime() { + return endTime; + } + + public void setEndTime(@javax.annotation.Nullable OffsetDateTime endTime) { + this.endTime = endTime; + } + + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + private Map additionalProperties; + + /** + * Set the additional (undeclared) property with the specified name and value. + * If the property does not already exist, create it otherwise replace it. + * + * @param key name of the property + * @param value value of the property + * @return the RbmSession instance itself + */ + public RbmSession putAdditionalProperty(String key, Object value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) property. + * + * @return a map of objects + */ + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + * + * @param key name of the property + * @return an object + */ + public Object getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RbmSession rbmSession = (RbmSession) o; + return Objects.equals(this.canInitiate, rbmSession.canInitiate) && + Objects.equals(this.id, rbmSession.id) && + Objects.equals(this.type, rbmSession.type) && + Objects.equals(this.startTime, rbmSession.startTime) && + Objects.equals(this.endTime, rbmSession.endTime)&& + Objects.equals(this.additionalProperties, rbmSession.additionalProperties); + } + + private static boolean equalsNullable(JsonNullable a, JsonNullable b) { + return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); + } + + @Override + public int hashCode() { + return Objects.hash(canInitiate, id, type, startTime, endTime, additionalProperties); + } + + private static int hashCodeNullable(JsonNullable a) { + if (a == null) { + return 1; + } + return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class RbmSession {\n"); + sb.append(" canInitiate: ").append(toIndentedString(canInitiate)).append("\n"); + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" startTime: ").append(toIndentedString(startTime)).append("\n"); + sb.append(" endTime: ").append(toIndentedString(endTime)).append("\n"); + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + return o == null ? "null" : o.toString().replace("\n", "\n "); + } + + + public static HashSet openapiFields; + public static HashSet openapiRequiredFields; + + static { + // a set of all properties/fields (JSON key names) + openapiFields = new HashSet(Arrays.asList("canInitiate", "id", "type", "startTime", "endTime")); + + // a set of required properties/fields (JSON key names) + openapiRequiredFields = new HashSet(Arrays.asList("canInitiate")); + } + + /** + * Validates the JSON Element and throws an exception if issues found + * + * @param jsonElement JSON Element + * @throws IOException if the JSON Element is invalid with respect to RbmSession + */ + public static void validateJsonElement(JsonElement jsonElement) throws IOException { + if (jsonElement == null) { + if (!RbmSession.openapiRequiredFields.isEmpty()) { // has required fields but JSON element is null + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The required field(s) %s in RbmSession is not found in the empty JSON string", RbmSession.openapiRequiredFields.toString())); + } + } + + // check to make sure all required properties/fields are present in the JSON string + for (String requiredField : RbmSession.openapiRequiredFields) { + if (jsonElement.getAsJsonObject().get(requiredField) == null) { + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The required field `%s` is not found in the JSON string: %s", requiredField, jsonElement.toString())); + } + } + JsonObject jsonObj = jsonElement.getAsJsonObject(); + if ((jsonObj.get("id") != null && !jsonObj.get("id").isJsonNull()) && !jsonObj.get("id").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `id` to be a primitive type in the JSON string but got `%s`", jsonObj.get("id").toString())); + } + if ((jsonObj.get("type") != null && !jsonObj.get("type").isJsonNull()) && !jsonObj.get("type").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `type` to be a primitive type in the JSON string but got `%s`", jsonObj.get("type").toString())); + } + } + + public static class CustomTypeAdapterFactory implements TypeAdapterFactory { + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (!RbmSession.class.isAssignableFrom(type.getRawType())) { + return null; // this class only serializes 'RbmSession' and its subtypes + } + final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); + final TypeAdapter thisAdapter + = gson.getDelegateAdapter(this, TypeToken.get(RbmSession.class)); + + return (TypeAdapter) new TypeAdapter() { + @Override + public void write(JsonWriter out, RbmSession value) throws IOException { + JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject(); + obj.remove("additionalProperties"); + // serialize additional properties + if (value.getAdditionalProperties() != null) { + for (Map.Entry entry : value.getAdditionalProperties().entrySet()) { + if (entry.getValue() instanceof String) + obj.addProperty(entry.getKey(), (String) entry.getValue()); + else if (entry.getValue() instanceof Number) + obj.addProperty(entry.getKey(), (Number) entry.getValue()); + else if (entry.getValue() instanceof Boolean) + obj.addProperty(entry.getKey(), (Boolean) entry.getValue()); + else if (entry.getValue() instanceof Character) + obj.addProperty(entry.getKey(), (Character) entry.getValue()); + else { + JsonElement jsonElement = gson.toJsonTree(entry.getValue()); + if (jsonElement.isJsonArray()) { + obj.add(entry.getKey(), jsonElement.getAsJsonArray()); + } else { + obj.add(entry.getKey(), jsonElement.getAsJsonObject()); + } + } + } + } + elementAdapter.write(out, obj); + } + + @Override + public RbmSession read(JsonReader in) throws IOException { + JsonElement jsonElement = elementAdapter.read(in); + validateJsonElement(jsonElement); + JsonObject jsonObj = jsonElement.getAsJsonObject(); + // store additional fields in the deserialized instance + RbmSession instance = thisAdapter.fromJsonTree(jsonObj); + for (Map.Entry entry : jsonObj.entrySet()) { + if (!openapiFields.contains(entry.getKey())) { + if (entry.getValue().isJsonPrimitive()) { // primitive type + if (entry.getValue().getAsJsonPrimitive().isString()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsString()); + else if (entry.getValue().getAsJsonPrimitive().isNumber()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsNumber()); + else if (entry.getValue().getAsJsonPrimitive().isBoolean()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsBoolean()); + else + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The field `%s` has unknown primitive type. Value: %s", entry.getKey(), entry.getValue().toString())); + } else if (entry.getValue().isJsonArray()) { + instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), List.class)); + } else { // JSON object + instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), HashMap.class)); + } + } + } + return instance; + } + + }.nullSafe(); + } + } + + /** + * Create an instance of RbmSession given an JSON string + * + * @param jsonString JSON string + * @return An instance of RbmSession + * @throws IOException if the JSON string is invalid with respect to RbmSession + */ + public static RbmSession fromJson(String jsonString) throws IOException { + return JSON.getGson().fromJson(jsonString, RbmSession.class); + } + + /** + * Convert an instance of RbmSession to an JSON string + * + * @return JSON string + */ + public String toJson() { + return JSON.getGson().toJson(this); + } +} + diff --git a/src/main/java/com/bandwidth/sdk/model/RbmSuggestionResponse.java b/src/main/java/com/bandwidth/sdk/model/RbmSuggestionResponse.java index a6ebbe36..4f07e28a 100644 --- a/src/main/java/com/bandwidth/sdk/model/RbmSuggestionResponse.java +++ b/src/main/java/com/bandwidth/sdk/model/RbmSuggestionResponse.java @@ -59,7 +59,7 @@ public class RbmSuggestionResponse { public static final String SERIALIZED_NAME_POSTBACK_DATA = "postbackData"; @SerializedName(SERIALIZED_NAME_POSTBACK_DATA) @javax.annotation.Nullable - private byte[] postbackData; + private String postbackData; public static final String SERIALIZED_NAME_PAIRED_MESSAGE_ID = "pairedMessageId"; @SerializedName(SERIALIZED_NAME_PAIRED_MESSAGE_ID) @@ -75,7 +75,7 @@ public RbmSuggestionResponse text(@javax.annotation.Nullable String text) { } /** - * The text associated with the suggestion response. + * The text of the suggestion the user tapped. * @return text */ @javax.annotation.Nullable @@ -88,21 +88,21 @@ public void setText(@javax.annotation.Nullable String text) { } - public RbmSuggestionResponse postbackData(@javax.annotation.Nullable byte[] postbackData) { + public RbmSuggestionResponse postbackData(@javax.annotation.Nullable String postbackData) { this.postbackData = postbackData; return this; } /** - * Base64 payload the customer receives when the reply is clicked. + * Payload the customer receives when the reply is clicked. * @return postbackData */ @javax.annotation.Nullable - public byte[] getPostbackData() { + public String getPostbackData() { return postbackData; } - public void setPostbackData(@javax.annotation.Nullable byte[] postbackData) { + public void setPostbackData(@javax.annotation.Nullable String postbackData) { this.postbackData = postbackData; } @@ -181,7 +181,7 @@ public boolean equals(Object o) { } RbmSuggestionResponse rbmSuggestionResponse = (RbmSuggestionResponse) o; return Objects.equals(this.text, rbmSuggestionResponse.text) && - Arrays.equals(this.postbackData, rbmSuggestionResponse.postbackData) && + Objects.equals(this.postbackData, rbmSuggestionResponse.postbackData) && Objects.equals(this.pairedMessageId, rbmSuggestionResponse.pairedMessageId)&& Objects.equals(this.additionalProperties, rbmSuggestionResponse.additionalProperties); } @@ -192,7 +192,7 @@ private static boolean equalsNullable(JsonNullable a, JsonNullable b) @Override public int hashCode() { - return Objects.hash(text, Arrays.hashCode(postbackData), pairedMessageId, additionalProperties); + return Objects.hash(text, postbackData, pairedMessageId, additionalProperties); } private static int hashCodeNullable(JsonNullable a) { @@ -250,6 +250,9 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti if ((jsonObj.get("text") != null && !jsonObj.get("text").isJsonNull()) && !jsonObj.get("text").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `text` to be a primitive type in the JSON string but got `%s`", jsonObj.get("text").toString())); } + if ((jsonObj.get("postbackData") != null && !jsonObj.get("postbackData").isJsonNull()) && !jsonObj.get("postbackData").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `postbackData` to be a primitive type in the JSON string but got `%s`", jsonObj.get("postbackData").toString())); + } if ((jsonObj.get("pairedMessageId") != null && !jsonObj.get("pairedMessageId").isJsonNull()) && !jsonObj.get("pairedMessageId").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `pairedMessageId` to be a primitive type in the JSON string but got `%s`", jsonObj.get("pairedMessageId").toString())); } diff --git a/src/main/java/com/bandwidth/sdk/model/StatusCallbackMessage.java b/src/main/java/com/bandwidth/sdk/model/StatusCallbackMessage.java index 62321bca..cbc2b4de 100644 --- a/src/main/java/com/bandwidth/sdk/model/StatusCallbackMessage.java +++ b/src/main/java/com/bandwidth/sdk/model/StatusCallbackMessage.java @@ -17,6 +17,7 @@ import com.bandwidth.sdk.model.MessageDirectionEnum; import com.bandwidth.sdk.model.MultiChannelMessageChannelEnum; import com.bandwidth.sdk.model.PriorityEnum; +import com.bandwidth.sdk.model.RbmSession; import com.google.gson.TypeAdapter; import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; @@ -124,6 +125,11 @@ public class StatusCallbackMessage { @javax.annotation.Nullable private MultiChannelMessageChannelEnum channel; + public static final String SERIALIZED_NAME_SESSION = "session"; + @SerializedName(SERIALIZED_NAME_SESSION) + @javax.annotation.Nullable + private RbmSession session; + public StatusCallbackMessage() { } @@ -389,6 +395,25 @@ public void setChannel(@javax.annotation.Nullable MultiChannelMessageChannelEnum this.channel = channel; } + + public StatusCallbackMessage session(@javax.annotation.Nullable RbmSession session) { + this.session = session; + return this; + } + + /** + * Get session + * @return session + */ + @javax.annotation.Nullable + public RbmSession getSession() { + return session; + } + + public void setSession(@javax.annotation.Nullable RbmSession session) { + this.session = session; + } + /** * A container for additional, undeclared properties. * This is a holder for any undeclared properties as specified with @@ -456,13 +481,14 @@ public boolean equals(Object o) { Objects.equals(this.tag, statusCallbackMessage.tag) && Objects.equals(this.media, statusCallbackMessage.media) && Objects.equals(this.priority, statusCallbackMessage.priority) && - Objects.equals(this.channel, statusCallbackMessage.channel)&& + Objects.equals(this.channel, statusCallbackMessage.channel) && + Objects.equals(this.session, statusCallbackMessage.session)&& Objects.equals(this.additionalProperties, statusCallbackMessage.additionalProperties); } @Override public int hashCode() { - return Objects.hash(id, owner, applicationId, time, segmentCount, direction, to, from, text, tag, media, priority, channel, additionalProperties); + return Objects.hash(id, owner, applicationId, time, segmentCount, direction, to, from, text, tag, media, priority, channel, session, additionalProperties); } @Override @@ -482,6 +508,7 @@ public String toString() { sb.append(" media: ").append(toIndentedString(media)).append("\n"); sb.append(" priority: ").append(toIndentedString(priority)).append("\n"); sb.append(" channel: ").append(toIndentedString(channel)).append("\n"); + sb.append(" session: ").append(toIndentedString(session)).append("\n"); sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); sb.append("}"); return sb.toString(); @@ -501,7 +528,7 @@ private String toIndentedString(Object o) { static { // a set of all properties/fields (JSON key names) - openapiFields = new HashSet(Arrays.asList("id", "owner", "applicationId", "time", "segmentCount", "direction", "to", "from", "text", "tag", "media", "priority", "channel")); + openapiFields = new HashSet(Arrays.asList("id", "owner", "applicationId", "time", "segmentCount", "direction", "to", "from", "text", "tag", "media", "priority", "channel", "session")); // a set of required properties/fields (JSON key names) openapiRequiredFields = new HashSet(Arrays.asList("id", "owner", "applicationId", "time", "segmentCount", "direction", "to", "from")); @@ -565,6 +592,10 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti if (jsonObj.get("channel") != null && !jsonObj.get("channel").isJsonNull()) { MultiChannelMessageChannelEnum.validateJsonElement(jsonObj.get("channel")); } + // validate the optional field `session` + if (jsonObj.get("session") != null && !jsonObj.get("session").isJsonNull()) { + RbmSession.validateJsonElement(jsonObj.get("session")); + } } public static class CustomTypeAdapterFactory implements TypeAdapterFactory { diff --git a/src/main/java/com/bandwidth/sdk/model/StatusCallbackTypeEnum.java b/src/main/java/com/bandwidth/sdk/model/StatusCallbackTypeEnum.java index dc2a8b4d..401dec3a 100644 --- a/src/main/java/com/bandwidth/sdk/model/StatusCallbackTypeEnum.java +++ b/src/main/java/com/bandwidth/sdk/model/StatusCallbackTypeEnum.java @@ -24,7 +24,7 @@ import com.google.gson.stream.JsonWriter; /** - * The possible status callbacks when sending an MT SMS or MMS or RBM message: - `message-sending` indicates that Bandwidth is sending the message to the upstream provider. - `message-sent` indicates that the message has left the Bandwidth network and is in transit to the provider. - `message-delivered` indicates that the message was successfully delivered to handset. - `message-failed` indicates that the message could not be sent to the intended recipient. - `message-read` indicates that the RBM message was read by the recipient. + * The possible status callbacks when sending an MT SMS or MMS or RBM message: - `message-sending` indicates that Bandwidth is sending the message to the upstream provider. - `message-sent` indicates that the message has left the Bandwidth network and is in transit to the provider. - `message-delivered` indicates that the message was successfully delivered to handset. - `message-failed` indicates that the message could not be sent to the intended recipient. - `message-read` indicates that the RBM message was read by the recipient. - `session-started` indicates that a previously exchanged RBM message is now part of an RCS interactive session and is no longer billed individually. */ @JsonAdapter(StatusCallbackTypeEnum.Adapter.class) public enum StatusCallbackTypeEnum { @@ -37,7 +37,9 @@ public enum StatusCallbackTypeEnum { MESSAGE_FAILED("message-failed"), - MESSAGE_READ("message-read"); + MESSAGE_READ("message-read"), + + SESSION_STARTED("session-started"); private String value; diff --git a/src/main/java/com/bandwidth/sdk/model/TransferDisconnectCallback.java b/src/main/java/com/bandwidth/sdk/model/TransferDisconnectCallback.java index a83e132f..eddb46ec 100644 --- a/src/main/java/com/bandwidth/sdk/model/TransferDisconnectCallback.java +++ b/src/main/java/com/bandwidth/sdk/model/TransferDisconnectCallback.java @@ -24,6 +24,8 @@ import java.net.URI; import java.time.OffsetDateTime; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import org.openapitools.jackson.nullable.JsonNullable; import com.google.gson.Gson; @@ -154,6 +156,21 @@ public class TransferDisconnectCallback { @javax.annotation.Nullable private String errorId; + public static final String SERIALIZED_NAME_SIP_RESPONSE_CODE = "sipResponseCode"; + @SerializedName(SERIALIZED_NAME_SIP_RESPONSE_CODE) + @javax.annotation.Nullable + private Integer sipResponseCode; + + public static final String SERIALIZED_NAME_SIP_STATUS_LINE = "sipStatusLine"; + @SerializedName(SERIALIZED_NAME_SIP_STATUS_LINE) + @javax.annotation.Nullable + private String sipStatusLine; + + public static final String SERIALIZED_NAME_SIP_HEADERS = "sipHeaders"; + @SerializedName(SERIALIZED_NAME_SIP_HEADERS) + @javax.annotation.Nullable + private Map sipHeaders = new HashMap<>(); + public TransferDisconnectCallback() { } @@ -536,6 +553,71 @@ public void setErrorId(@javax.annotation.Nullable String errorId) { this.errorId = errorId; } + + public TransferDisconnectCallback sipResponseCode(@javax.annotation.Nullable Integer sipResponseCode) { + this.sipResponseCode = sipResponseCode; + return this; + } + + /** + * (optional) The SIP status code of the final response that rejected an outbound call's (or transferred leg's) INVITE (e.g. 486 for busy, 603 for decline). Present only when the call was rejected with a SIP response. + * @return sipResponseCode + */ + @javax.annotation.Nullable + public Integer getSipResponseCode() { + return sipResponseCode; + } + + public void setSipResponseCode(@javax.annotation.Nullable Integer sipResponseCode) { + this.sipResponseCode = sipResponseCode; + } + + + public TransferDisconnectCallback sipStatusLine(@javax.annotation.Nullable String sipStatusLine) { + this.sipStatusLine = sipStatusLine; + return this; + } + + /** + * (optional) The full SIP status line, exactly as received, of the final response that rejected an outbound call's INVITE. The reason phrase can help distinguish outcomes that share a status code, such as `603 Network Blocked` and `603 Decline`. Present only when an outbound call was rejected with a SIP response. + * @return sipStatusLine + */ + @javax.annotation.Nullable + public String getSipStatusLine() { + return sipStatusLine; + } + + public void setSipStatusLine(@javax.annotation.Nullable String sipStatusLine) { + this.sipStatusLine = sipStatusLine; + } + + + public TransferDisconnectCallback sipHeaders(@javax.annotation.Nullable Map sipHeaders) { + this.sipHeaders = sipHeaders; + return this; + } + + public TransferDisconnectCallback putSipHeadersItem(String key, String sipHeadersItem) { + if (this.sipHeaders == null) { + this.sipHeaders = new HashMap<>(); + } + this.sipHeaders.put(key, sipHeadersItem); + return this; + } + + /** + * (optional) Map of SIP headers, with lowercase keys (SIP headers are case-insensitive). On the Initiate callback, contains the customer-supplied X-* headers from the original INVITE; present only for inbound SIP URI calls with custom headers. On the Disconnect and Transfer Disconnect callbacks, contains a single `reason` key holding the raw, unmodified `Reason` header value from the final SIP response that rejected an outbound call (or transferred leg); present only when that response included a `Reason` header (for example, `v=analytics1` call-analytics block information from a terminating carrier). If the response carries more than one `Reason` header, all values are returned in the order received, separated by `, `. Note - on the Initiate callback, keys preserve the original SIP header name in lowercase rather than Bandwidth's usual camelCase JSON convention, since these are passthrough values from the caller's SIP INVITE, not Bandwidth-defined fields. If the same header name is sent more than once in the INVITE, only the last value is kept. The example shown is for the Initiate callback; on the Disconnect and Transfer Disconnect callbacks the only key is `reason`. + * @return sipHeaders + */ + @javax.annotation.Nullable + public Map getSipHeaders() { + return sipHeaders; + } + + public void setSipHeaders(@javax.annotation.Nullable Map sipHeaders) { + this.sipHeaders = sipHeaders; + } + /** * A container for additional, undeclared properties. * This is a holder for any undeclared properties as specified with @@ -610,7 +692,10 @@ public boolean equals(Object o) { Objects.equals(this.transferTo, transferDisconnectCallback.transferTo) && Objects.equals(this.cause, transferDisconnectCallback.cause) && Objects.equals(this.errorMessage, transferDisconnectCallback.errorMessage) && - Objects.equals(this.errorId, transferDisconnectCallback.errorId)&& + Objects.equals(this.errorId, transferDisconnectCallback.errorId) && + Objects.equals(this.sipResponseCode, transferDisconnectCallback.sipResponseCode) && + Objects.equals(this.sipStatusLine, transferDisconnectCallback.sipStatusLine) && + Objects.equals(this.sipHeaders, transferDisconnectCallback.sipHeaders)&& Objects.equals(this.additionalProperties, transferDisconnectCallback.additionalProperties); } @@ -620,7 +705,7 @@ private static boolean equalsNullable(JsonNullable a, JsonNullable b) @Override public int hashCode() { - return Objects.hash(eventType, eventTime, accountId, applicationId, from, to, direction, callId, callUrl, parentCallId, enqueuedTime, startTime, answerTime, endTime, tag, transferCallerId, transferTo, cause, errorMessage, errorId, additionalProperties); + return Objects.hash(eventType, eventTime, accountId, applicationId, from, to, direction, callId, callUrl, parentCallId, enqueuedTime, startTime, answerTime, endTime, tag, transferCallerId, transferTo, cause, errorMessage, errorId, sipResponseCode, sipStatusLine, sipHeaders, additionalProperties); } private static int hashCodeNullable(JsonNullable a) { @@ -654,6 +739,9 @@ public String toString() { sb.append(" cause: ").append(toIndentedString(cause)).append("\n"); sb.append(" errorMessage: ").append(toIndentedString(errorMessage)).append("\n"); sb.append(" errorId: ").append(toIndentedString(errorId)).append("\n"); + sb.append(" sipResponseCode: ").append(toIndentedString(sipResponseCode)).append("\n"); + sb.append(" sipStatusLine: ").append(toIndentedString(sipStatusLine)).append("\n"); + sb.append(" sipHeaders: ").append(toIndentedString(sipHeaders)).append("\n"); sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); sb.append("}"); return sb.toString(); @@ -673,7 +761,7 @@ private String toIndentedString(Object o) { static { // a set of all properties/fields (JSON key names) - openapiFields = new HashSet(Arrays.asList("eventType", "eventTime", "accountId", "applicationId", "from", "to", "direction", "callId", "callUrl", "parentCallId", "enqueuedTime", "startTime", "answerTime", "endTime", "tag", "transferCallerId", "transferTo", "cause", "errorMessage", "errorId")); + openapiFields = new HashSet(Arrays.asList("eventType", "eventTime", "accountId", "applicationId", "from", "to", "direction", "callId", "callUrl", "parentCallId", "enqueuedTime", "startTime", "answerTime", "endTime", "tag", "transferCallerId", "transferTo", "cause", "errorMessage", "errorId", "sipResponseCode", "sipStatusLine", "sipHeaders")); // a set of required properties/fields (JSON key names) openapiRequiredFields = new HashSet(0); @@ -738,6 +826,9 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti if ((jsonObj.get("errorId") != null && !jsonObj.get("errorId").isJsonNull()) && !jsonObj.get("errorId").isJsonPrimitive()) { throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `errorId` to be a primitive type in the JSON string but got `%s`", jsonObj.get("errorId").toString())); } + if ((jsonObj.get("sipStatusLine") != null && !jsonObj.get("sipStatusLine").isJsonNull()) && !jsonObj.get("sipStatusLine").isJsonPrimitive()) { + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `sipStatusLine` to be a primitive type in the JSON string but got `%s`", jsonObj.get("sipStatusLine").toString())); + } } public static class CustomTypeAdapterFactory implements TypeAdapterFactory { From 326bc014d13a00fbe121d07a0eea3988b3705126 Mon Sep 17 00:00:00 2001 From: ckoegel Date: Tue, 3 Nov 2026 12:28:46 -0500 Subject: [PATCH 2/3] update unit tests --- .../unit/models/DisconnectCallbackTest.java | 21 ++++- .../models/InboundCallbackMessageTest.java | 12 ++- .../MultiChannelActionCalendarEventTest.java | 4 +- .../sdk/unit/models/RbmActionBaseTest.java | 4 +- .../sdk/unit/models/RbmActionDialTest.java | 4 +- .../sdk/unit/models/RbmActionOpenUrlTest.java | 4 +- .../models/RbmActionViewLocationTest.java | 4 +- .../sdk/unit/models/RbmSessionTest.java | 83 +++++++++++++++++++ .../models/RbmSuggestionResponseTest.java | 4 +- .../models/StatusCallbackMessageTest.java | 12 ++- .../models/StatusCallbackTypeEnumTest.java | 1 + .../TransferDisconnectCallbackTest.java | 30 ++++++- 12 files changed, 167 insertions(+), 16 deletions(-) create mode 100644 src/test/java/com/bandwidth/sdk/unit/models/RbmSessionTest.java diff --git a/src/test/java/com/bandwidth/sdk/unit/models/DisconnectCallbackTest.java b/src/test/java/com/bandwidth/sdk/unit/models/DisconnectCallbackTest.java index 024219e5..64df5431 100644 --- a/src/test/java/com/bandwidth/sdk/unit/models/DisconnectCallbackTest.java +++ b/src/test/java/com/bandwidth/sdk/unit/models/DisconnectCallbackTest.java @@ -16,6 +16,7 @@ import java.net.URI; import java.time.OffsetDateTime; +import java.util.Map; import com.bandwidth.sdk.model.DisconnectCallback; import com.bandwidth.sdk.model.CallDirectionEnum; @@ -45,7 +46,9 @@ public class DisconnectCallbackTest { .errorId("errorId") .tag("tag") .sipCallId("sipCallId") - .sipResponseCode(200); + .sipResponseCode(603) + .sipStatusLine("SIP/2.0 603 Network Blocked") + .sipHeaders(Map.of("reason", "v=analytics1")); /** * Model tests for DisconnectCallback @@ -206,4 +209,20 @@ public void sipCallIdTest() { public void sipResponseCodeTest() { assertThat(model.getSipResponseCode(), instanceOf(Integer.class)); } + + /** + * Test the property 'sipStatusLine' + */ + @Test + public void sipStatusLineTest() { + assertThat(model.getSipStatusLine(), instanceOf(String.class)); + } + + /** + * Test the property 'sipHeaders' + */ + @Test + public void sipHeadersTest() { + assertThat(model.getSipHeaders(), instanceOf(Map.class)); + } } diff --git a/src/test/java/com/bandwidth/sdk/unit/models/InboundCallbackMessageTest.java b/src/test/java/com/bandwidth/sdk/unit/models/InboundCallbackMessageTest.java index 19b13be8..c9632c15 100644 --- a/src/test/java/com/bandwidth/sdk/unit/models/InboundCallbackMessageTest.java +++ b/src/test/java/com/bandwidth/sdk/unit/models/InboundCallbackMessageTest.java @@ -25,6 +25,7 @@ import com.bandwidth.sdk.model.MultiChannelMessageContent; import com.bandwidth.sdk.model.PriorityEnum; import com.bandwidth.sdk.model.RbmLocationResponse; +import com.bandwidth.sdk.model.RbmSession; import com.bandwidth.sdk.model.RbmSuggestionResponse; import static org.hamcrest.CoreMatchers.instanceOf; @@ -50,7 +51,8 @@ public class InboundCallbackMessageTest { .channel(MultiChannelMessageChannelEnum.SMS) .content(new MultiChannelMessageContent()) .suggestionResponse(new RbmSuggestionResponse()) - .locationResponse(new RbmLocationResponse()); + .locationResponse(new RbmLocationResponse()) + .session(new RbmSession()); /** * Model tests for InboundCallbackMessage @@ -188,4 +190,12 @@ public void locationResponseTest() { assertThat(model.getLocationResponse(), instanceOf(RbmLocationResponse.class)); } + /** + * Test the property 'session' + */ + @Test + public void sessionTest() { + assertThat(model.getSession(), instanceOf(RbmSession.class)); + } + } diff --git a/src/test/java/com/bandwidth/sdk/unit/models/MultiChannelActionCalendarEventTest.java b/src/test/java/com/bandwidth/sdk/unit/models/MultiChannelActionCalendarEventTest.java index 2441adfe..8a362011 100644 --- a/src/test/java/com/bandwidth/sdk/unit/models/MultiChannelActionCalendarEventTest.java +++ b/src/test/java/com/bandwidth/sdk/unit/models/MultiChannelActionCalendarEventTest.java @@ -30,7 +30,7 @@ public class MultiChannelActionCalendarEventTest { private final MultiChannelActionCalendarEvent model = new MultiChannelActionCalendarEvent() .type(RbmActionTypeEnum.REPLY) .text("text") - .postbackData(new byte[]{1, 2, 3}) + .postbackData("postbackData") .title("title") .startTime(OffsetDateTime.now()) .endTime(OffsetDateTime.now()) @@ -65,7 +65,7 @@ public void textTest() { */ @Test public void postbackDataTest() { - assertThat(model.getPostbackData(), instanceOf(byte[].class)); + assertThat(model.getPostbackData(), instanceOf(String.class)); } /** diff --git a/src/test/java/com/bandwidth/sdk/unit/models/RbmActionBaseTest.java b/src/test/java/com/bandwidth/sdk/unit/models/RbmActionBaseTest.java index ab75e5e9..5ad72d58 100644 --- a/src/test/java/com/bandwidth/sdk/unit/models/RbmActionBaseTest.java +++ b/src/test/java/com/bandwidth/sdk/unit/models/RbmActionBaseTest.java @@ -28,7 +28,7 @@ public class RbmActionBaseTest { private final RbmActionBase model = new RbmActionBase() .type(RbmActionTypeEnum.REPLY) .text("text") - .postbackData(new byte[]{1, 2, 3}); + .postbackData("postbackData"); /** * Model tests for RbmActionBase @@ -59,7 +59,7 @@ public void textTest() { */ @Test public void postbackDataTest() { - assertThat(model.getPostbackData(), instanceOf(byte[].class)); + assertThat(model.getPostbackData(), instanceOf(String.class)); } } diff --git a/src/test/java/com/bandwidth/sdk/unit/models/RbmActionDialTest.java b/src/test/java/com/bandwidth/sdk/unit/models/RbmActionDialTest.java index fc9f47f4..b40c1df1 100644 --- a/src/test/java/com/bandwidth/sdk/unit/models/RbmActionDialTest.java +++ b/src/test/java/com/bandwidth/sdk/unit/models/RbmActionDialTest.java @@ -28,7 +28,7 @@ public class RbmActionDialTest { private final RbmActionDial model = new RbmActionDial() .type(RbmActionTypeEnum.DIAL_PHONE) .text("text") - .postbackData(new byte[]{1, 2, 3}) + .postbackData("postbackData") .phoneNumber("phoneNumber"); /** @@ -60,7 +60,7 @@ public void textTest() { */ @Test public void postbackDataTest() { - assertThat(model.getPostbackData(), instanceOf(byte[].class)); + assertThat(model.getPostbackData(), instanceOf(String.class)); } /** diff --git a/src/test/java/com/bandwidth/sdk/unit/models/RbmActionOpenUrlTest.java b/src/test/java/com/bandwidth/sdk/unit/models/RbmActionOpenUrlTest.java index c7533f65..8daba878 100644 --- a/src/test/java/com/bandwidth/sdk/unit/models/RbmActionOpenUrlTest.java +++ b/src/test/java/com/bandwidth/sdk/unit/models/RbmActionOpenUrlTest.java @@ -33,7 +33,7 @@ public class RbmActionOpenUrlTest { private final RbmActionOpenUrl model = new RbmActionOpenUrl() .type(RbmActionTypeEnum.OPEN_URL) .text("text") - .postbackData(new byte[]{1, 2, 3}) + .postbackData("postbackData") .url(URI.create("https://bandwidth.com")) .application(RbmOpenUrlEnum.BROWSER) .webviewViewMode(RbmWebViewEnum.FULL); @@ -67,7 +67,7 @@ public void textTest() { */ @Test public void postbackDataTest() { - assertThat(model.getPostbackData(), instanceOf(byte[].class)); + assertThat(model.getPostbackData(), instanceOf(String.class)); } /** diff --git a/src/test/java/com/bandwidth/sdk/unit/models/RbmActionViewLocationTest.java b/src/test/java/com/bandwidth/sdk/unit/models/RbmActionViewLocationTest.java index cf754d36..ba72d1df 100644 --- a/src/test/java/com/bandwidth/sdk/unit/models/RbmActionViewLocationTest.java +++ b/src/test/java/com/bandwidth/sdk/unit/models/RbmActionViewLocationTest.java @@ -28,7 +28,7 @@ public class RbmActionViewLocationTest { private final RbmActionViewLocation model = new RbmActionViewLocation() .type(RbmActionTypeEnum.SHOW_LOCATION) .text("text") - .postbackData(new byte[]{1, 2, 3}) + .postbackData("postbackData") .latitude(1.0) .longitude(1.0) .label("label"); @@ -62,7 +62,7 @@ public void textTest() { */ @Test public void postBackDataTest() { - assertThat(model.getPostbackData(), instanceOf(byte[].class)); + assertThat(model.getPostbackData(), instanceOf(String.class)); } /** diff --git a/src/test/java/com/bandwidth/sdk/unit/models/RbmSessionTest.java b/src/test/java/com/bandwidth/sdk/unit/models/RbmSessionTest.java new file mode 100644 index 00000000..95570b3e --- /dev/null +++ b/src/test/java/com/bandwidth/sdk/unit/models/RbmSessionTest.java @@ -0,0 +1,83 @@ +/* + * Bandwidth + * Bandwidth's Communication APIs + * + * The version of the OpenAPI document: 1.0.0 + * Contact: letstalk@bandwidth.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package com.bandwidth.sdk.unit.models; + +import org.junit.jupiter.api.Test; + +import java.time.OffsetDateTime; +import com.bandwidth.sdk.model.RbmSession; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * Model tests for RbmSession + */ +public class RbmSessionTest { + private final RbmSession model = new RbmSession() + .canInitiate(true) + .id("id") + .type("type") + .startTime(OffsetDateTime.now()) + .endTime(OffsetDateTime.now()); + + /** + * Model tests for RbmSession + */ + @Test + public void testRbmSession() { + assertThat(model, instanceOf(RbmSession.class)); + } + + /** + * Test the property 'canInitiate' + */ + @Test + public void canInitiateTest() { + assertThat(model.getCanInitiate(), instanceOf(Boolean.class)); + } + + /** + * Test the property 'id' + */ + @Test + public void idTest() { + assertThat(model.getId(), instanceOf(String.class)); + } + + /** + * Test the property 'type' + */ + @Test + public void typeTest() { + assertThat(model.getType(), instanceOf(String.class)); + } + + /** + * Test the property 'startTime' + */ + @Test + public void startTimeTest() { + assertThat(model.getStartTime(), instanceOf(OffsetDateTime.class)); + } + + /** + * Test the property 'endTime' + */ + @Test + public void endTimeTest() { + assertThat(model.getEndTime(), instanceOf(OffsetDateTime.class)); + } + +} diff --git a/src/test/java/com/bandwidth/sdk/unit/models/RbmSuggestionResponseTest.java b/src/test/java/com/bandwidth/sdk/unit/models/RbmSuggestionResponseTest.java index 6cf4c2b1..45189141 100644 --- a/src/test/java/com/bandwidth/sdk/unit/models/RbmSuggestionResponseTest.java +++ b/src/test/java/com/bandwidth/sdk/unit/models/RbmSuggestionResponseTest.java @@ -26,7 +26,7 @@ public class RbmSuggestionResponseTest { private final RbmSuggestionResponse model = new RbmSuggestionResponse() .text("text") - .postbackData(new byte[]{1, 2, 3}) + .postbackData("postbackData") .pairedMessageId("pairedMessageId"); /** @@ -50,7 +50,7 @@ public void textTest() { */ @Test public void postbackDataTest() { - assertThat(model.getPostbackData(), instanceOf(byte[].class)); + assertThat(model.getPostbackData(), instanceOf(String.class)); } /** diff --git a/src/test/java/com/bandwidth/sdk/unit/models/StatusCallbackMessageTest.java b/src/test/java/com/bandwidth/sdk/unit/models/StatusCallbackMessageTest.java index feb478f0..6e1afdf0 100644 --- a/src/test/java/com/bandwidth/sdk/unit/models/StatusCallbackMessageTest.java +++ b/src/test/java/com/bandwidth/sdk/unit/models/StatusCallbackMessageTest.java @@ -23,6 +23,7 @@ import com.bandwidth.sdk.model.MessageDirectionEnum; import com.bandwidth.sdk.model.MultiChannelMessageChannelEnum; import com.bandwidth.sdk.model.PriorityEnum; +import com.bandwidth.sdk.model.RbmSession; import com.bandwidth.sdk.model.StatusCallbackMessage; import static org.hamcrest.CoreMatchers.instanceOf; @@ -45,7 +46,8 @@ public class StatusCallbackMessageTest { .tag("tag") .media(new ArrayList<>()) .priority(PriorityEnum.DEFAULT) - .channel(MultiChannelMessageChannelEnum.SMS); + .channel(MultiChannelMessageChannelEnum.SMS) + .session(new RbmSession()); /** * Model tests for StatusCallbackMessage @@ -159,4 +161,12 @@ public void channelTest() { assertThat(model.getChannel(), instanceOf(MultiChannelMessageChannelEnum.class)); } + /** + * Test the property 'session' + */ + @Test + public void sessionTest() { + assertThat(model.getSession(), instanceOf(RbmSession.class)); + } + } diff --git a/src/test/java/com/bandwidth/sdk/unit/models/StatusCallbackTypeEnumTest.java b/src/test/java/com/bandwidth/sdk/unit/models/StatusCallbackTypeEnumTest.java index ffda4eda..e6a0204a 100644 --- a/src/test/java/com/bandwidth/sdk/unit/models/StatusCallbackTypeEnumTest.java +++ b/src/test/java/com/bandwidth/sdk/unit/models/StatusCallbackTypeEnumTest.java @@ -34,6 +34,7 @@ public void testStatusCallbackTypeEnum() { assertThat(StatusCallbackTypeEnum.MESSAGE_DELIVERED.toString(), equalTo("message-delivered")); assertThat(StatusCallbackTypeEnum.MESSAGE_FAILED.toString(), equalTo("message-failed")); assertThat(StatusCallbackTypeEnum.MESSAGE_READ.toString(), equalTo("message-read")); + assertThat(StatusCallbackTypeEnum.SESSION_STARTED.toString(), equalTo("session-started")); } diff --git a/src/test/java/com/bandwidth/sdk/unit/models/TransferDisconnectCallbackTest.java b/src/test/java/com/bandwidth/sdk/unit/models/TransferDisconnectCallbackTest.java index 7eb52e51..bffa44d5 100644 --- a/src/test/java/com/bandwidth/sdk/unit/models/TransferDisconnectCallbackTest.java +++ b/src/test/java/com/bandwidth/sdk/unit/models/TransferDisconnectCallbackTest.java @@ -16,6 +16,7 @@ import java.net.URI; import java.time.OffsetDateTime; +import java.util.Map; import com.bandwidth.sdk.model.TransferDisconnectCallback; import com.bandwidth.sdk.model.CallDirectionEnum; @@ -46,7 +47,10 @@ public class TransferDisconnectCallbackTest { .transferTo("transferTo") .cause("cause") .errorMessage("errorMessage") - .errorId("errorId"); + .errorId("errorId") + .sipResponseCode(603) + .sipStatusLine("SIP/2.0 603 Network Blocked") + .sipHeaders(Map.of("reason", "v=analytics1")); /** * Model tests for TransferDisconnectCallback @@ -216,4 +220,28 @@ public void errorIdTest() { assertThat(model.getErrorId(), instanceOf(String.class)); } + /** + * Test the property 'sipResponseCode' + */ + @Test + public void sipResponseCodeTest() { + assertThat(model.getSipResponseCode(), instanceOf(Integer.class)); + } + + /** + * Test the property 'sipStatusLine' + */ + @Test + public void sipStatusLineTest() { + assertThat(model.getSipStatusLine(), instanceOf(String.class)); + } + + /** + * Test the property 'sipHeaders' + */ + @Test + public void sipHeadersTest() { + assertThat(model.getSipHeaders(), instanceOf(Map.class)); + } + } From 158f4a60382212bea82e44a23aa76aa48099208e Mon Sep 17 00:00:00 2001 From: ckoegel Date: Tue, 3 Nov 2026 12:28:50 -0500 Subject: [PATCH 3/3] update smoke test --- .../com/bandwidth/sdk/smoke/MultiChannelApiTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/bandwidth/sdk/smoke/MultiChannelApiTest.java b/src/test/java/com/bandwidth/sdk/smoke/MultiChannelApiTest.java index 3e16d942..d1d6b3cc 100644 --- a/src/test/java/com/bandwidth/sdk/smoke/MultiChannelApiTest.java +++ b/src/test/java/com/bandwidth/sdk/smoke/MultiChannelApiTest.java @@ -186,7 +186,7 @@ public void createMultiChannelRBMTextMessageTest() throws ApiException { new MultiChannelAction(new RbmActionDial() .type(RbmActionTypeEnum.DIAL_PHONE) .text("Call Us") - .postbackData(new byte[]{1, 2, 3}) + .postbackData("postbackData") .phoneNumber(BW_NUMBER) ) )) @@ -238,7 +238,7 @@ public void createMultiChannelRBMTextMessageTest() throws ApiException { assertThat(rbmActionDial.getType(), instanceOf(RbmActionTypeEnum.class)); assertThat(rbmActionDial.getType(), equalTo(RbmActionTypeEnum.DIAL_PHONE)); assertThat(rbmActionDial.getText(), instanceOf(String.class)); - assertThat(rbmActionDial.getPostbackData(), instanceOf(byte[].class)); + assertThat(rbmActionDial.getPostbackData(), instanceOf(String.class)); assertThat(rbmActionDial.getPhoneNumber(), instanceOf(String.class)); assertThat(channelListObject.getOwner(), equalTo(BW_NUMBER)); } @@ -260,7 +260,7 @@ public void createMultiChannelRBMMediaMessageTest() throws ApiException { new MultiChannelAction(new RbmActionDial() .type(RbmActionTypeEnum.DIAL_PHONE) .text("Call Us") - .postbackData(new byte[]{1, 2, 3}) + .postbackData("postbackData") .phoneNumber(BW_NUMBER) ) )) @@ -315,7 +315,7 @@ public void createMultiChannelRBMMediaMessageTest() throws ApiException { assertThat(rbmActionDial.getType(), instanceOf(RbmActionTypeEnum.class)); assertThat(rbmActionDial.getType(), equalTo(RbmActionTypeEnum.DIAL_PHONE)); assertThat(rbmActionDial.getText(), instanceOf(String.class)); - assertThat(rbmActionDial.getPostbackData(), instanceOf(byte[].class)); + assertThat(rbmActionDial.getPostbackData(), instanceOf(String.class)); assertThat(rbmActionDial.getPhoneNumber(), instanceOf(String.class)); assertThat(channelListObject.getOwner(), equalTo(BW_NUMBER)); } @@ -411,7 +411,7 @@ public void createMultiChannelRBMRichCarouselMessageTest() throws ApiException { new MultiChannelAction(new RbmActionDial() .type(RbmActionTypeEnum.DIAL_PHONE) .text("Call Us") - .postbackData(new byte[]{1, 2, 3}) + .postbackData("postbackData") .phoneNumber(BW_NUMBER) ) )), @@ -481,7 +481,7 @@ public void createMultiChannelRBMRichCarouselMessageTest() throws ApiException { assertThat(rbmActionDial.getType(), instanceOf(RbmActionTypeEnum.class)); assertThat(rbmActionDial.getType(), equalTo(RbmActionTypeEnum.DIAL_PHONE)); assertThat(rbmActionDial.getText(), instanceOf(String.class)); - assertThat(rbmActionDial.getPostbackData(), instanceOf(byte[].class)); + assertThat(rbmActionDial.getPostbackData(), instanceOf(String.class)); assertThat(rbmActionDial.getPhoneNumber(), instanceOf(String.class)); assertThat(rbmCard.getCardContents().get(0), instanceOf(RbmCardContent.class)); RbmCardContent card2 = rbmCard.getCardContents().get(1);