vonage 7.35.0 → 8.0.0.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +87 -880
- data/lib/vonage/account.rb +0 -2
- data/lib/vonage/applications.rb +4 -12
- data/lib/vonage/basic.rb +1 -1
- data/lib/vonage/bearer_token.rb +1 -1
- data/lib/vonage/client.rb +0 -72
- data/lib/vonage/client_error.rb +1 -1
- data/lib/vonage/config.rb +1 -7
- data/lib/vonage/conversations/events.rb +0 -12
- data/lib/vonage/conversations/legs.rb +0 -6
- data/lib/vonage/conversations/members.rb +0 -15
- data/lib/vonage/conversations/users.rb +0 -15
- data/lib/vonage/conversations.rb +0 -30
- data/lib/vonage/conversions.rb +0 -2
- data/lib/vonage/errors.rb +20 -37
- data/lib/vonage/gsm7.rb +1 -1
- data/lib/vonage/http.rb +3 -3
- data/lib/vonage/jwt.rb +0 -17
- data/lib/vonage/key_secret_params.rb +2 -3
- data/lib/vonage/keys.rb +1 -17
- data/lib/vonage/logger.rb +3 -0
- data/lib/vonage/messaging/channels/messenger.rb +0 -2
- data/lib/vonage/messaging/channels/mms.rb +3 -13
- data/lib/vonage/messaging/channels/sms.rb +0 -2
- data/lib/vonage/messaging/channels/viber.rb +2 -11
- data/lib/vonage/messaging/channels/whats_app.rb +1 -5
- data/lib/vonage/messaging/message.rb +1 -4
- data/lib/vonage/messaging.rb +4 -43
- data/lib/vonage/namespace.rb +68 -137
- data/lib/vonage/number_insight.rb +0 -1
- data/lib/vonage/numbers.rb +17 -40
- data/lib/vonage/server_error.rb +1 -1
- data/lib/vonage/signature.rb +6 -29
- data/lib/vonage/sms.rb +20 -25
- data/lib/vonage/verify.rb +0 -2
- data/lib/vonage/version.rb +1 -1
- data/lib/vonage/video/archives.rb +58 -35
- data/lib/vonage/video/list_response.rb +11 -0
- data/lib/vonage/video/moderation.rb +22 -7
- data/lib/vonage/video/signals.rb +9 -4
- data/lib/vonage/video/streams.rb +12 -6
- data/lib/vonage/video.rb +13 -56
- data/lib/vonage/voice/actions/connect.rb +9 -45
- data/lib/vonage/voice/actions/conversation.rb +4 -10
- data/lib/vonage/voice/actions/input.rb +3 -26
- data/lib/vonage/voice/actions/notify.rb +3 -8
- data/lib/vonage/voice/actions/pay.rb +107 -0
- data/lib/vonage/voice/actions/record.rb +4 -52
- data/lib/vonage/voice/actions/stream.rb +3 -7
- data/lib/vonage/voice/actions/talk.rb +4 -29
- data/lib/vonage/voice/ncco.rb +1 -3
- data/lib/vonage/voice/talk.rb +1 -11
- data/lib/vonage/voice.rb +0 -24
- data/lib/vonage.rb +0 -4
- data/vonage.gemspec +1 -3
- metadata +12 -116
- data/lib/vonage/api_error.rb +0 -33
- data/lib/vonage/basic_and_bearer_token.rb +0 -18
- data/lib/vonage/basic_and_signature.rb +0 -22
- data/lib/vonage/conversation/event/list_response.rb +0 -11
- data/lib/vonage/conversation/event.rb +0 -108
- data/lib/vonage/conversation/list_response.rb +0 -11
- data/lib/vonage/conversation/member/list_response.rb +0 -11
- data/lib/vonage/conversation/member.rb +0 -134
- data/lib/vonage/conversation/user/conversations_list_response.rb +0 -11
- data/lib/vonage/conversation/user/sessions_list_response.rb +0 -11
- data/lib/vonage/conversation/user.rb +0 -67
- data/lib/vonage/conversation.rb +0 -164
- data/lib/vonage/identity_insights/insights_builder.rb +0 -75
- data/lib/vonage/identity_insights.rb +0 -75
- data/lib/vonage/meetings/applications.rb +0 -28
- data/lib/vonage/meetings/dial_in_numbers/list_response.rb +0 -11
- data/lib/vonage/meetings/dial_in_numbers.rb +0 -26
- data/lib/vonage/meetings/recordings.rb +0 -42
- data/lib/vonage/meetings/rooms/list_response.rb +0 -11
- data/lib/vonage/meetings/rooms.rb +0 -167
- data/lib/vonage/meetings/sessions/list_response.rb +0 -11
- data/lib/vonage/meetings/sessions.rb +0 -31
- data/lib/vonage/meetings/themes/list_response.rb +0 -11
- data/lib/vonage/meetings/themes.rb +0 -239
- data/lib/vonage/meetings.rb +0 -50
- data/lib/vonage/messaging/channels/rcs.rb +0 -44
- data/lib/vonage/network_authentication/client_authentication.rb +0 -39
- data/lib/vonage/network_authentication/server_authentication.rb +0 -47
- data/lib/vonage/network_authentication.rb +0 -22
- data/lib/vonage/network_number_verification.rb +0 -92
- data/lib/vonage/network_sim_swap.rb +0 -84
- data/lib/vonage/number_insight_2.rb +0 -21
- data/lib/vonage/proactive_connect/events/list_response.rb +0 -11
- data/lib/vonage/proactive_connect/events.rb +0 -71
- data/lib/vonage/proactive_connect/item.rb +0 -116
- data/lib/vonage/proactive_connect/items/file_response.rb +0 -32
- data/lib/vonage/proactive_connect/items/list_response.rb +0 -11
- data/lib/vonage/proactive_connect/items.rb +0 -116
- data/lib/vonage/proactive_connect/list.rb +0 -186
- data/lib/vonage/proactive_connect/lists/list_response.rb +0 -11
- data/lib/vonage/proactive_connect/lists.rb +0 -38
- data/lib/vonage/proactive_connect.rb +0 -43
- data/lib/vonage/subaccounts/balance_transfers/list_response.rb +0 -11
- data/lib/vonage/subaccounts/credit_transfers/list_response.rb +0 -11
- data/lib/vonage/subaccounts/list_response.rb +0 -15
- data/lib/vonage/subaccounts.rb +0 -203
- data/lib/vonage/users/list_response.rb +0 -11
- data/lib/vonage/users.rb +0 -156
- data/lib/vonage/verify2/channels/email.rb +0 -36
- data/lib/vonage/verify2/channels/silent_auth.rb +0 -46
- data/lib/vonage/verify2/channels/sms.rb +0 -63
- data/lib/vonage/verify2/channels/voice.rb +0 -32
- data/lib/vonage/verify2/channels/whats_app.rb +0 -45
- data/lib/vonage/verify2/channels/whats_app_interactive.rb +0 -32
- data/lib/vonage/verify2/start_verification_options.rb +0 -63
- data/lib/vonage/verify2/template_fragments/list_response.rb +0 -11
- data/lib/vonage/verify2/template_fragments.rb +0 -125
- data/lib/vonage/verify2/templates/list_response.rb +0 -11
- data/lib/vonage/verify2/templates.rb +0 -86
- data/lib/vonage/verify2/workflow.rb +0 -39
- data/lib/vonage/verify2/workflow_builder.rb +0 -25
- data/lib/vonage/verify2.rb +0 -112
- data/lib/vonage/video/archives/list_response.rb +0 -11
- data/lib/vonage/video/broadcasts/list_response.rb +0 -11
- data/lib/vonage/video/broadcasts.rb +0 -75
- data/lib/vonage/video/captions.rb +0 -67
- data/lib/vonage/video/connections/list_response.rb +0 -11
- data/lib/vonage/video/connections.rb +0 -29
- data/lib/vonage/video/renders/list_response.rb +0 -11
- data/lib/vonage/video/renders.rb +0 -107
- data/lib/vonage/video/sip.rb +0 -48
- data/lib/vonage/video/streams/list_response.rb +0 -11
- data/lib/vonage/video/web_socket.rb +0 -62
- data/lib/vonage/voice/actions/transfer.rb +0 -83
- data/lib/vonage/voice/actions/wait.rb +0 -43
data/README.md
CHANGED
|
@@ -11,34 +11,22 @@ need a Vonage account. Sign up [for free at vonage.com][signup].
|
|
|
11
11
|
* [Requirements](#requirements)
|
|
12
12
|
* [Installation](#installation)
|
|
13
13
|
* [Usage](#usage)
|
|
14
|
-
* [Authentication](#authentication)
|
|
15
|
-
* [Basic Authentication](#basic-authentication)
|
|
16
|
-
* [JWT Authentication](#jwt-authentication)
|
|
17
|
-
* [Signature Authentication](#signature-authentication)
|
|
18
14
|
* [Logging](#logging)
|
|
19
|
-
* [Exceptions](#exceptions)
|
|
20
15
|
* [Overriding the default hosts](#overriding-the-default-hosts)
|
|
21
|
-
* [HTTP Client Configuration](#http-client-configuration)
|
|
22
16
|
* [JWT authentication](#jwt-authentication)
|
|
23
17
|
* [Webhook signatures](#webhook-signatures)
|
|
24
18
|
* [Pagination](#pagination)
|
|
25
|
-
* [
|
|
26
|
-
* [Verify API v2](#verify-api-v2)
|
|
27
|
-
* [Voice API](#voice-api)
|
|
28
|
-
* [NCCO Builder](#ncco-builder)
|
|
29
|
-
* [Identity Insights API](#identity-insights-api)
|
|
19
|
+
* [NCCO Builder](#ncco-builder)
|
|
30
20
|
* [Documentation](#documentation)
|
|
31
|
-
* [
|
|
32
|
-
* [
|
|
21
|
+
* [Frequently Asked Questions](#frequently-asked-questions)
|
|
22
|
+
* [Supported APIs](#supported-apis)
|
|
33
23
|
* [License](#license)
|
|
34
|
-
* [Contribute](#contribute)
|
|
35
24
|
|
|
36
25
|
|
|
37
26
|
## Requirements
|
|
38
27
|
|
|
39
|
-
Vonage Ruby supports MRI/CRuby (
|
|
28
|
+
Vonage Ruby supports MRI/CRuby (2.5 or newer), JRuby (9.2.x), and Truffleruby.
|
|
40
29
|
|
|
41
|
-
JRuby and Truffleruby are supported in theory, but aren't tested against as part of the CI pipeline.
|
|
42
30
|
|
|
43
31
|
## Installation
|
|
44
32
|
|
|
@@ -62,7 +50,7 @@ require 'vonage'
|
|
|
62
50
|
Then construct a client object with your key and secret:
|
|
63
51
|
|
|
64
52
|
```ruby
|
|
65
|
-
client = Vonage::Client.new
|
|
53
|
+
client = Vonage::Client.new(api_key: 'YOUR-API-KEY', api_secret: 'YOUR-API-SECRET')
|
|
66
54
|
```
|
|
67
55
|
|
|
68
56
|
You can now use the client object to call Vonage APIs. For example, to send an SMS:
|
|
@@ -71,263 +59,12 @@ You can now use the client object to call Vonage APIs. For example, to send an S
|
|
|
71
59
|
client.sms.send(from: 'Ruby', to: '447700900000', text: 'Hello world')
|
|
72
60
|
```
|
|
73
61
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
All requests to the Vonage APIs are authenticated, so the `Client` object will need access to your Vonage credentials. Different Vonage API products support different authenitcations methods, so the credentials required will depend on the authenticaton method used. A few API products also support [multiple authentication methods](#products-with-multiple-authentication-methods).
|
|
79
|
-
|
|
80
|
-
Currently, all Vonage API products support one or more of the following authentication methods:
|
|
81
|
-
|
|
82
|
-
- [Basic Authentication](#basic-authentication)
|
|
83
|
-
- [JWT Authentication](#jwt-authentication)
|
|
84
|
-
- [Signature Authentication](#signature-authentication)
|
|
85
|
-
|
|
86
|
-
For a complete list of which products support which authentication methods, please refer to the [Vonage documentation on this topic](https://developer.vonage.com/en/getting-started/concepts/authentication).
|
|
87
|
-
|
|
88
|
-
Providing the necessary credentials to the client can be done in a number of ways. You can pass the credentials as keyword arguments when calling `Client.new`, for example in order to provide you API Key and API Secret you could use the `api_key` and `api_secret` keyword arguments respectively. You can pass the value for these arguments directly in the method call like so:
|
|
89
|
-
|
|
90
|
-
```ruby
|
|
91
|
-
client = Vonage::Client.new(api_key: 'abc123', api_secret: 'abc123456789')
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
Generally though, and especially for production code or any code that you plan to push up to source control, you will want to avoid exposing your credentials directly in this way and instead use environment variables to define your credentials.
|
|
95
|
-
|
|
96
|
-
> [!CAUTION]
|
|
97
|
-
> When setting environment variables locally, if using a file to do this (such as in an `.env` file), you should include the name of that file in a `.gitignore` file if you are intending to push your code up to source control.
|
|
98
|
-
|
|
99
|
-
You can choose to define your own custom environment variables and then use Ruby's `ENV` hash to pass them in as the values for your keyword arguments, for example:
|
|
100
|
-
|
|
101
|
-
```ruby
|
|
102
|
-
client = Vonage::Client.new(api_key: ENV['MY_API_KEY'], api_secret: ENV['MY_API_SECRET'])
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
A less verbose approach is to instantiate the client *without* passing in keyword arguments for the authentication credentials.
|
|
106
|
-
|
|
107
|
-
```ruby
|
|
108
|
-
client = Vonage::Client.new
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
In this case the `Config` object used by the `Client` will search your environment for some pre-defined environment variables and use the values of those variables if defined. The names of these pre-defined environment variables are outlined in the sections below on the specific authentication methods.
|
|
112
|
-
|
|
113
|
-
Note that some Vonage API products support multiple authentication methods. In these cases the Ruby SDK sets a default authentication method for that product, which can be over-ridden with a configuration setting. You can learn more about this in the section on [Products with Multiple Authentication Methods](#products-with-multiple-authentication-methods).
|
|
114
|
-
|
|
115
|
-
#### Basic Authentication
|
|
116
|
-
|
|
117
|
-
For products that use Basic Authentication, the Ruby SDK sets an `Authorization` header on the HTTP request with a value containing a Base64 encoded version of your API key and secret. You can read more about this authentication method in the [Vonage documentation](https://developer.vonage.com/en/getting-started/concepts/authentication?source=getting-started#basic-authentication).
|
|
118
|
-
|
|
119
|
-
To set the header the SDK requires access to your API Key and API Secret. You can either:
|
|
120
|
-
|
|
121
|
-
1. Pass them in to the `Client` constructor as `api_key` and `api_secret` keyword arguments, either passing in the values directly or as environement variables with custom keys:
|
|
122
|
-
```ruby
|
|
123
|
-
client = Vonage::Client.new(api_key: 'abc123', api_secret: 'abc123456789')
|
|
124
|
-
```
|
|
125
|
-
or
|
|
126
|
-
```
|
|
127
|
-
# .env
|
|
128
|
-
MY_API_KEY=abc123
|
|
129
|
-
MY_API_SECRET=abc123456789
|
|
130
|
-
```
|
|
131
|
-
```ruby
|
|
132
|
-
client = Vonage::Client.new(api_key: ENV['MY_API_KEY'], api_secret: ENV['MY_API_SECRET'])
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
2. Set them as environment variables with the `VONAGE_API_KEY` and `VONAGE_API_SECRET` keys and then call the constructor without the keyword arguments:
|
|
136
|
-
```
|
|
137
|
-
# .env
|
|
138
|
-
VONAGE_API_KEY=abc123
|
|
139
|
-
VONAGE_API_SECRET=abc123456789
|
|
140
|
-
```
|
|
141
|
-
```ruby
|
|
142
|
-
client = Vonage::Client.new
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
#### JWT Authentication
|
|
146
|
-
|
|
147
|
-
For products that use Bearer (JWT) Authentication, the Ruby SDK sets an `Authorization` header on the HTTP request with a value containing a JSON Web Token (JWT) derived from an Application ID and Private Key. You can read more about this authentication method in the [Vonage documentation](https://developer.vonage.com/en/getting-started/concepts/authentication#json-web-tokens), but in brief you will need to create a Vonage Application (for example via the [Vonage Developer Dashboard](https://dashboard.vonage.com/applications), [Application API](https://developer.vonage.com/en/application/overview), or [Vonage CLI](https://github.com/vonage/vonage-cli)). This Application will be assigned a unique ID upon creation. You can then generate a public and private key pair specific to this Application.
|
|
148
|
-
|
|
149
|
-
The Ruby SDK automatically generates the JWT and sets the `Authorization` header for you. To do this it requires access to an Application ID and assocaited Private Key. You can either:
|
|
150
|
-
|
|
151
|
-
1. Pass them in to the `Client` constructor as `application_id` and `private_key` keyword arguments, either passing in the values directly or as environement variables with custom keys:
|
|
152
|
-
```ruby
|
|
153
|
-
client = Vonage::Client.new(
|
|
154
|
-
application_id: '78d335fa-323d-0114-9c3d-d6f0d48968cf',
|
|
155
|
-
private_key: '-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFA........'
|
|
156
|
-
)
|
|
157
|
-
```
|
|
158
|
-
or
|
|
159
|
-
```
|
|
160
|
-
# .env
|
|
161
|
-
MY_APPLICATION_ID=78d335fa-323d-0114-9c3d-d6f0d48968cf
|
|
162
|
-
MY_PRIVATE_KEY=-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFA........
|
|
163
|
-
```
|
|
164
|
-
```ruby
|
|
165
|
-
client = Vonage::Client.new(application_id: ENV['MY_APPLICATION_ID'], private_key: ENV['MY_PRIVATE_KEY'])
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
2. Set them as environment variables with the `VONAGE_APPLICATION_ID` and `VONAGE_PRIVATE_KEY` keys and then call the constructor without the keyword arguments:
|
|
169
|
-
```
|
|
170
|
-
# .env
|
|
171
|
-
VONAGE_APPLICATION_ID=78d335fa-323d-0114-9c3d-d6f0d48968cf
|
|
172
|
-
VONAGE_PRIVATE_KEY=-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFA........
|
|
173
|
-
```
|
|
174
|
-
```ruby
|
|
175
|
-
client = Vonage::Client.new
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
##### Using a Private Key File
|
|
179
|
-
|
|
180
|
-
Using the private key directly, whether to pass it in as a keyword argument or set it as an environment variable, can be a litle bit unweildy. Another option is to store it in a `.key` file and then read the contents of that file in as necessary.
|
|
181
|
-
|
|
182
|
-
> [!CAUTION]
|
|
183
|
-
> You should include the name of your Private Key file in a `.gitignore` file if you are intending to push your code up to source control.
|
|
184
|
-
|
|
185
|
-
For example, if you had your private key stored in a file called `private.key` in the root directory of your Ruby application, you could:
|
|
186
|
-
|
|
187
|
-
1. Read the contents of the file in using Ruby's `File.read` method when passing the `private_key` keyword argument to the `Client` constructor, either by passing the filepath directly or as an environement variables with a custom key:
|
|
188
|
-
```ruby
|
|
189
|
-
client = Vonage::Client.new(
|
|
190
|
-
application_id: '78d335fa-323d-0114-9c3d-d6f0d48968cf',
|
|
191
|
-
private_key: File.read('/private.key)
|
|
192
|
-
)
|
|
193
|
-
```
|
|
194
|
-
or
|
|
195
|
-
```
|
|
196
|
-
# .env
|
|
197
|
-
MY_APPLICATION_ID=78d335fa-323d-0114-9c3d-d6f0d48968cf
|
|
198
|
-
MY_PRIVATE_KEY_PATH=/private.key
|
|
199
|
-
```
|
|
200
|
-
```ruby
|
|
201
|
-
client = Vonage::Client.new(application_id: ENV['MY_APPLICATION_ID'], private_key: File.read(ENV['MY_PRIVATE_KEY_PATH']))
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
2. Set the path as an environment variable with the `VONAGE_PRIVATE_KEY_PATH` key (note: this is used in place of the `VONAGE_PRIVATE_KEY` key) and then call the constructor without the keyword arguments:
|
|
205
|
-
```
|
|
206
|
-
# .env
|
|
207
|
-
VONAGE_APPLICATION_ID=78d335fa-323d-0114-9c3d-d6f0d48968cf
|
|
208
|
-
VONAGE_PRIVATE_KEY_PATH=/private.key
|
|
209
|
-
```
|
|
210
|
-
```ruby
|
|
211
|
-
client = Vonage::Client.new
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
If `VONAGE_PRIVATE_KEY_PATH` is set, then the Ruby SDK will attempt to read in the contents of the file at the path provided and use those contents as the Private Key.
|
|
215
|
-
|
|
216
|
-
> [!TIP]
|
|
217
|
-
> You can download your Private Key file when creating or updating a Vonage Application in the [Vonage Developer Dashboard](https://dashboard.vonage.com/applications), or creating a Vonage Application with the [Vonage CLI](https://github.com/vonage/vonage-cli). You can also create your own file using the value of the `keys.private_key` param provided in the HTTP response when creating a Vonage Application using the [Application API](https://developer.vonage.com/en/application/overview).
|
|
218
|
-
|
|
219
|
-
##### Custom JWTs
|
|
220
|
-
|
|
221
|
-
By default the library generates a short lived JWT per request (the default `ttl` is `900` seconds). If you need to generate a long lived JWT for multiple requests or specify JWT claims directly use `Vonage::JWT.generate` to generate a custom JWT and then pass that in to the `Client` constructor using the `token` option. For example:
|
|
222
|
-
|
|
223
|
-
```ruby
|
|
224
|
-
claims = {
|
|
225
|
-
application_id: ENV['VONAGE_APPLICATION_ID'],
|
|
226
|
-
private_key: File.read(ENV['VONAGE_PRIVATE_KEY_PATH']),
|
|
227
|
-
nbf: 1483315200,
|
|
228
|
-
ttl: 3600
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
token = Vonage::JWT.generate(claims)
|
|
232
|
-
|
|
233
|
-
client = Vonage::Client.new(token: token)
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
The `Client` object will then use the JWT that you passed in for any API requests rather than generating one on-the-fly for each request.
|
|
237
|
-
|
|
238
|
-
> [!NOTE]
|
|
239
|
-
> 1. Unlike with the `Client` constructor, you **must** set `application_id` and `private_key` as key-value pairs in the `claims` Hash when generating a custom JWT.
|
|
240
|
-
> 2. You can choose to set *either* `ttl` *or* `exp` in the `claims`:
|
|
241
|
-
> - If you set *both* `ttl` is ignored and `exp` is used
|
|
242
|
-
> - If you choose to set `exp` this must be set as the number of seconds since the UNIX epoch (if using `ttl` the generator calculates this for you)
|
|
243
|
-
|
|
244
|
-
Documentation for the Vonage Ruby JWT generator gem can be found at: https://www.rubydoc.info/gems/vonage-jwt
|
|
62
|
+
For production you can specify the `VONAGE_API_KEY` and `VONAGE_API_SECRET`
|
|
63
|
+
environment variables instead of specifying the key and secret explicitly,
|
|
64
|
+
keeping your credentials out of source control.
|
|
245
65
|
|
|
246
|
-
The documentation outlines all the possible parameters you can use to customize and build a token with.
|
|
247
|
-
|
|
248
|
-
#### Signature Authentication
|
|
249
|
-
|
|
250
|
-
Signature authentication signs the request using a signature created via a signing algorithm and using your Vonage Signature Secret. You can read more about this authentication method in the [Vonage documentation](https://developer.vonage.com/en/getting-started/concepts/signing-messages).
|
|
251
|
-
|
|
252
|
-
To create the signature the SDK requires access to your API Key and Signature Secret. You can either:
|
|
253
|
-
|
|
254
|
-
1. Pass them in to the `Client` constructor as `api_key` and `signature_secret` keyword arguments, either passing in the values directly or as environement variables with custom keys:
|
|
255
|
-
```ruby
|
|
256
|
-
client = Vonage::Client.new(api_key: 'abc123', signature_secret: 'hdEooIhQYgo5XAcmbfLfpy5ROcEwGbjcwj6EvywwvYNOxKWj71')
|
|
257
|
-
```
|
|
258
|
-
or
|
|
259
|
-
```
|
|
260
|
-
# .env
|
|
261
|
-
MY_API_KEY=abc123
|
|
262
|
-
MY_SIGNATURE_SECRET=hdEooIhQYgo5XAcmbfLfpy5ROcEwGbjcwj6EvywwvYNOxKWj71
|
|
263
|
-
```
|
|
264
|
-
```ruby
|
|
265
|
-
client = Vonage::Client.new(api_key: ENV['MY_API_KEY'], api_secret: ENV['MY_SIGNATURE_SECRET'])
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
2. Set them as environment variables with the `VONAGE_API_KEY` and `VONAGE_SIGNATURE_SECRET` keys and then call the constructor without the keyword arguments:
|
|
269
|
-
```
|
|
270
|
-
# .env
|
|
271
|
-
VONAGE_API_KEY=abc123
|
|
272
|
-
VONAGE_SIGNATURE_SECRET=hdEooIhQYgo5XAcmbfLfpy5ROcEwGbjcwj6EvywwvYNOxKWj71
|
|
273
|
-
```
|
|
274
|
-
```ruby
|
|
275
|
-
client = Vonage::Client.new
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
By default, the Ruby SDK uses the MD5 HASH algorithm to generate the signature. If you've set a different algorithm in your [Vonage API Settings](https://dashboard.vonage.com/settings), you'll need to over-ride the default when instantiating the `Client` object, for example:
|
|
279
|
-
|
|
280
|
-
```ruby
|
|
281
|
-
client = Vonage::Client.new(
|
|
282
|
-
api_key: 'abc123',
|
|
283
|
-
signature_secret: 'hdEooIhQYgo5XAcmbfLfpy5ROcEwGbjcwj6EvywwvYNOxKWj71',
|
|
284
|
-
signature_method: 'sha512'
|
|
285
|
-
)
|
|
286
|
-
```
|
|
287
66
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
```
|
|
291
|
-
# .env
|
|
292
|
-
VONAGE_API_KEY=abc123
|
|
293
|
-
VONAGE_SIGNATURE_SECRET=hdEooIhQYgo5XAcmbfLfpy5ROcEwGbjcwj6EvywwvYNOxKWj71
|
|
294
|
-
VONAGE_SIGNATURE_METHOD=sha512
|
|
295
|
-
```
|
|
296
|
-
```ruby
|
|
297
|
-
client = Vonage::Client.new
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
Supported algorithms are:
|
|
301
|
-
|
|
302
|
-
- `md5hash`
|
|
303
|
-
- `md5` (HMAC)
|
|
304
|
-
- `sha1`
|
|
305
|
-
- `sha256`
|
|
306
|
-
- `sha512`
|
|
307
|
-
|
|
308
|
-
#### Products with Multiple Authentication Methods
|
|
309
|
-
|
|
310
|
-
Some Vonage API products support more than one authentication method. For these products the Ruby SDK sets a default authentication method, but this default can be over-ridden in the `Client` configuration using the `authentication_preference` setting. For example, the Messages API supports both Basic Authentication and Bearer Token (JWT) Authentication. For its Messages API implementation the Ruby SDK defaults to Bearer Token (JWT) Authentication and so you would normally need to provide a Vonage Application ID and Private Key as credentials in order to authenticate when using the Messages API via the Ruby SDK. However, you can instead provide your Vonage API Key and API Secret and set the `Client` object to use Basic Authentication instead:
|
|
311
|
-
|
|
312
|
-
```
|
|
313
|
-
# .env
|
|
314
|
-
VONAGE_API_KEY=abc123
|
|
315
|
-
VONAGE_API_SECRET=abc123456789
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
```ruby
|
|
319
|
-
client = Vonage::Client.new(authentication_preference: :basic)
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
Below is a list of Vonage API products currently implemented in the Ruby SDK that support more than one authentication method.
|
|
323
|
-
|
|
324
|
-
| Product | Authentication Methods | Default | Over-ride Key |
|
|
325
|
-
|---|---|---|---|
|
|
326
|
-
| Messages API | JWT, Basic | JWT | `:basic` |
|
|
327
|
-
| Verify API v2 | JWT, Basic | JWT | `:basic` |
|
|
328
|
-
| SMS API | Basic, Signature | Basic | `:signature` |
|
|
329
|
-
|
|
330
|
-
### Logging
|
|
67
|
+
## Logging
|
|
331
68
|
|
|
332
69
|
Use the logger option to specify a logger. For example:
|
|
333
70
|
|
|
@@ -343,48 +80,8 @@ By default the library sets the logger to `Rails.logger` if it is defined.
|
|
|
343
80
|
|
|
344
81
|
To disable logging set the logger to `nil`.
|
|
345
82
|
|
|
346
|
-
### Exceptions
|
|
347
|
-
|
|
348
|
-
Where exceptions result from an error response from the Vonage API (HTTP responses that aren't ion the range `2xx` or `3xx`), the `Net::HTTPResponse` object will be available as a property of the `Exception` object via a `http_response` getter method (where there is no `Net::HTTPResponse` object associated with the exception, the value of `http_response` will be `nil`).
|
|
349
83
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
```ruby
|
|
353
|
-
begin
|
|
354
|
-
verification_request = client.verify2.start_verification(
|
|
355
|
-
brand: 'Acme',
|
|
356
|
-
workflow: [{channel: 'sms', to: '44700000000'}]
|
|
357
|
-
)
|
|
358
|
-
rescue Vonage::APIError => error
|
|
359
|
-
if error.http_response
|
|
360
|
-
error.http_response # => #<Net::HTTPUnauthorized 401 Unauthorized readbody=true>
|
|
361
|
-
error.http_response_code # => "401"
|
|
362
|
-
error.http_response_headers # => {"date"=>["Sun, 24 Sep 2023 11:08:47 GMT"], ...rest of headers}
|
|
363
|
-
error.http_response_body # => {"title"=>"Unauthorized", ...rest of body}
|
|
364
|
-
end
|
|
365
|
-
end
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
For certain legacy API products, such as the [SMS API](https://developer.vonage.com/en/messaging/sms/overview), [Verify v1 API](https://developer.vonage.com/en/verify/verify-v1/overview) and [Number Insight v1 API](https://developer.vonage.com/en/number-insight/overview), a `200` response is received even in situations where there is an API-related error. For exceptions raised in these situation, rather than a `Net::HTTPResponse` object, a `Vonage::Response` object will be made available as a property of the exception via a `response` getter method. The properties on this object will depend on the response data provided by the API endpoint. For example:
|
|
369
|
-
|
|
370
|
-
```ruby
|
|
371
|
-
begin
|
|
372
|
-
sms = client.sms.send(
|
|
373
|
-
from: 'Vonage',
|
|
374
|
-
to: '44700000000',
|
|
375
|
-
text: 'Hello World!'
|
|
376
|
-
)
|
|
377
|
-
rescue Vonage::Error => error
|
|
378
|
-
if error.is_a? Vonage::ServiceError
|
|
379
|
-
error.response # => #<Vonage::Response:0x0000555b2e49d4f8>
|
|
380
|
-
error.response.messages.first.status # => "4"
|
|
381
|
-
error.response.messages.first.error_text # => "Bad Credentials"
|
|
382
|
-
error.response.http_response # => #<Net::HTTPOK 200 OK readbody=true>
|
|
383
|
-
end
|
|
384
|
-
end
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
### Overriding the default hosts
|
|
84
|
+
## Overriding the default hosts
|
|
388
85
|
|
|
389
86
|
To override the default hosts that the SDK uses for HTTP requests, you need to
|
|
390
87
|
specify the `api_host`, `rest_host` or both in the client configuration. For example:
|
|
@@ -398,155 +95,72 @@ client = Vonage::Client.new(
|
|
|
398
95
|
|
|
399
96
|
By default the hosts are set to `api.nexmo.com` and `rest.nexmo.com`, respectively.
|
|
400
97
|
|
|
401
|
-
### HTTP Client Configuration
|
|
402
|
-
|
|
403
|
-
It is possible to set configuration options on the HTTP client. This can be don in a couple of ways.
|
|
404
|
-
|
|
405
|
-
1. Using an `:http` key during `Vonage::Client` instantiation, for example:
|
|
406
|
-
```ruby
|
|
407
|
-
client = Vonage::Client.new(
|
|
408
|
-
api_key: 'YOUR-API-KEY',
|
|
409
|
-
api_secret: 'YOUR-API-SECRET',
|
|
410
|
-
http: {
|
|
411
|
-
max_retries: 1
|
|
412
|
-
}
|
|
413
|
-
)
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
2. By using the `http=` setter on the `Vonage::Config` object, for example:
|
|
417
|
-
```ruby
|
|
418
|
-
client = Vonage::Client.new(
|
|
419
|
-
api_key: 'YOUR-API-KEY',
|
|
420
|
-
api_secret: 'YOUR-API-SECRET'
|
|
421
|
-
)
|
|
422
|
-
|
|
423
|
-
client.config.http = { max_retries: 1 }
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
The Vonage Ruby SDK uses the [`Net::HTTP::Persistent` library](https://github.com/drbrain/net-http-persistent) as an HTTP client. For available configuration options see [the documentation for that library](https://www.rubydoc.info/gems/net-http-persistent/3.0.0/Net/HTTP/Persistent).
|
|
427
|
-
|
|
428
|
-
### Webhook signatures
|
|
429
|
-
|
|
430
|
-
Certain Vonage APIs provide signed [webhooks](https://developer.vonage.com/en/getting-started/concepts/webhooks) as a means of verifying the origin of the webhooks. The exact signing mechanism varies depending on the API.
|
|
431
|
-
|
|
432
|
-
#### Signature in Request Body
|
|
433
|
-
|
|
434
|
-
The [SMS API](https://developer.vonage.com/en/messaging/sms/overview) signs the webhook request using a hash digest. This is assigned to a `sig` parameter in the request body.
|
|
435
98
|
|
|
436
|
-
|
|
99
|
+
## JWT authentication
|
|
437
100
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
1. Pass all values to the method invocation.
|
|
441
|
-
|
|
442
|
-
```ruby
|
|
443
|
-
client = Vonage::Client.new
|
|
444
|
-
|
|
445
|
-
client.sms.verify_webhook_sig(
|
|
446
|
-
webhook_params: params,
|
|
447
|
-
signature_secret: 'secret',
|
|
448
|
-
signature_method: 'sha512'
|
|
449
|
-
) # => returns true if the signature is valid, false otherwise
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
2. Set `signature_secret` and `signature_method` at `Client` instantiation.
|
|
101
|
+
To call newer endpoints that support JWT authentication such as the Voice API and Messages API you'll
|
|
102
|
+
also need to specify the `application_id` and `private_key` options. For example:
|
|
453
103
|
|
|
454
104
|
```ruby
|
|
455
|
-
client = Vonage::Client.new(
|
|
456
|
-
signature_secret: 'secret',
|
|
457
|
-
signature_method: 'sha512'
|
|
458
|
-
)
|
|
459
|
-
|
|
460
|
-
client.sms.verify_webhook_sig(webhook_params: params) # => returns true if the signature is valid, false otherwise
|
|
105
|
+
client = Vonage::Client.new(application_id: application_id, private_key: private_key)
|
|
461
106
|
```
|
|
462
107
|
|
|
463
|
-
|
|
108
|
+
Both arguments should have string values corresponding to the `id` and `private_key`
|
|
109
|
+
values returned in a ["create an application"](https://developer.nexmo.com/api/application.v2#createApplication)
|
|
110
|
+
response. These credentials can be stored in a datastore, in environment variables,
|
|
111
|
+
on disk outside of source control, or in some kind of key management infrastructure.
|
|
464
112
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
client.config.signature_method = 'sha512'
|
|
469
|
-
|
|
470
|
-
client.sms.verify_webhook_sig(webhook_params: params) # => returns true if the signature is valid, false otherwise
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
4. Set `signature_secret` and `signature_method` as environment variables named `VONAGE_SIGNATURE_SECRET` and `VONAGE_SIGNATURE_METHOD`
|
|
113
|
+
By default the library generates a short lived JWT per request. To generate a long lived
|
|
114
|
+
JWT for multiple requests or to specify JWT claims directly use `Vonage::JWT.generate` and
|
|
115
|
+
the token option. For example:
|
|
474
116
|
|
|
475
117
|
```ruby
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
#### Signed JWT in Header
|
|
484
|
-
|
|
485
|
-
The [Voice API](https://developer.vonage.com/en/voice/voice-api/overview) and [Messages API](https://developer.vonage.com/en/messages/overview) both include an `Authorization` header in their webhook requests. The value of this header includes a JSON Web Token (JWT) signed using the Signature Secret associated with your Vonage account.
|
|
486
|
-
|
|
487
|
-
The `Vonage::Voice` and `Vonage::Messaging` classes both define a `verify_webhook_token` method which can be used to verify the JWT received in the webhook `Authorization` header.
|
|
488
|
-
|
|
489
|
-
To verify the JWT, you'll first need to extract it from the `Authorization` header. The header value will look something like the following:
|
|
490
|
-
|
|
491
|
-
```ruby
|
|
492
|
-
"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE1OTUyN" # remainder of token omitted for brevity
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
Note: we are only interested in the token itself, which comes *after* the word `Bearer` and the space.
|
|
496
|
-
|
|
497
|
-
Once you have extrated the token, you can pass it to the `verify_webhook_token` method in order to verify it.
|
|
498
|
-
|
|
499
|
-
The method also needs access to the the method also needs access to the signature secret associated with the Vonage account (available from the [Vonage Dashboard](https://dashboard.nexmo.com/settings)). There are a few different ways of providing this value to the method:
|
|
500
|
-
|
|
501
|
-
1. Pass all values to the method invocation.
|
|
502
|
-
|
|
503
|
-
```ruby
|
|
504
|
-
client = Vonage::Client.new
|
|
118
|
+
claims = {
|
|
119
|
+
application_id: application_id,
|
|
120
|
+
private_key: 'path/to/private.key',
|
|
121
|
+
nbf: 1483315200,
|
|
122
|
+
ttl: 800
|
|
123
|
+
}
|
|
505
124
|
|
|
506
|
-
|
|
507
|
-
token: extracted_token,
|
|
508
|
-
signature_secret: 'secret'
|
|
509
|
-
) # => returns true if the token is valid, false otherwise
|
|
510
|
-
```
|
|
125
|
+
token = Vonage::JWT.generate(claims)
|
|
511
126
|
|
|
512
|
-
|
|
127
|
+
client = Vonage::Client.new(token: token)
|
|
128
|
+
````
|
|
513
129
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
)
|
|
130
|
+
Documentation for the Vonage Ruby JWT generator gem can be found at
|
|
131
|
+
[https://www.rubydoc.info/github/nexmo/nexmo-jwt-ruby](https://www.rubydoc.info/github/nexmo/nexmo-jwt-ruby).
|
|
132
|
+
The documentation outlines all the possible parameters you can use to customize and build a token with.
|
|
518
133
|
|
|
519
|
-
|
|
520
|
-
```
|
|
134
|
+
## Webhook signatures
|
|
521
135
|
|
|
522
|
-
|
|
136
|
+
To check webhook signatures you'll also need to specify the `signature_secret` option. For example:
|
|
523
137
|
|
|
524
138
|
```ruby
|
|
525
139
|
client = Vonage::Client.new
|
|
526
140
|
client.config.signature_secret = 'secret'
|
|
527
141
|
client.config.signature_method = 'sha512'
|
|
528
142
|
|
|
529
|
-
client.
|
|
143
|
+
if client.signature.check(request.GET)
|
|
144
|
+
# valid signature
|
|
145
|
+
else
|
|
146
|
+
# invalid signature
|
|
147
|
+
end
|
|
530
148
|
```
|
|
531
149
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
```ruby
|
|
535
|
-
client = Vonage::Client.new
|
|
150
|
+
Alternatively you can set the `VONAGE_SIGNATURE_SECRET` environment variable.
|
|
536
151
|
|
|
537
|
-
|
|
538
|
-
```
|
|
152
|
+
Note: you'll need to contact support@nexmo.com to enable message signing on your account.
|
|
539
153
|
|
|
540
|
-
|
|
154
|
+
## Pagination
|
|
541
155
|
|
|
542
156
|
Vonage APIs paginate list requests. This means that if a collection is requested that is larger than the API default, the API will return the first page of items in the collection. The Ruby SDK provides an `auto_advance` parameter that will traverse through the pages and return all the results in one response object.
|
|
543
157
|
|
|
544
158
|
The `auto_advance` parameter is set to a default of `true` for the following APIs:
|
|
545
159
|
|
|
546
|
-
* [Account API](https://developer.
|
|
547
|
-
* [Application API](https://developer.
|
|
548
|
-
* [Conversation API](https://developer.
|
|
549
|
-
* [Voice API](https://developer.
|
|
160
|
+
* [Account API](https://developer.nexmo.com/api/developer/account)
|
|
161
|
+
* [Application API](https://developer.nexmo.com/api/application.v2)
|
|
162
|
+
* [Conversation API](https://developer.nexmo.com/api/conversation)
|
|
163
|
+
* [Voice API](https://developer.nexmo.com/api/voice)
|
|
550
164
|
|
|
551
165
|
To modify the `auto_advance` behavior you can specify it in your method:
|
|
552
166
|
|
|
@@ -554,366 +168,7 @@ To modify the `auto_advance` behavior you can specify it in your method:
|
|
|
554
168
|
client.applications.list(auto_advance: false)
|
|
555
169
|
```
|
|
556
170
|
|
|
557
|
-
|
|
558
|
-
## Messages API
|
|
559
|
-
|
|
560
|
-
The [Vonage Messages API](https://developer.vonage.com/messages/overview) allows you to send messages over a number of different channels, and various message types within each channel. See the Vonage Developer Documentation for a [complete API reference](https://developer.vonage.com/en/api/messages) listing all the channel and message type combinations.
|
|
561
|
-
|
|
562
|
-
### Sending a Message
|
|
563
|
-
|
|
564
|
-
The Ruby SDK implements a `Messaging` object which can be accessed via a `messaging` method on the `Client` object. The `Messaging` object has a `send` method which lets you send any message type via any channel.
|
|
565
|
-
|
|
566
|
-
```ruby
|
|
567
|
-
response = client.messaging.send(
|
|
568
|
-
# message data
|
|
569
|
-
)
|
|
570
|
-
```
|
|
571
|
-
|
|
572
|
-
There are a number of ways in which you can pass the necessary message data to the method.
|
|
573
|
-
|
|
574
|
-
**Using Keyword Arguments**
|
|
575
|
-
|
|
576
|
-
You can pass the message properties and their values as keyword arguments to the method. For example:
|
|
577
|
-
|
|
578
|
-
```ruby
|
|
579
|
-
response = client.messaging.send(
|
|
580
|
-
to: '447700900000',
|
|
581
|
-
from: '447700900001',
|
|
582
|
-
channel: 'sms',
|
|
583
|
-
message_type: 'text',
|
|
584
|
-
text: 'Hello world!'
|
|
585
|
-
)
|
|
586
|
-
```
|
|
587
|
-
|
|
588
|
-
**Spread a Hash**
|
|
589
|
-
|
|
590
|
-
For more complex message structures, you can define the message as a Hash literal and then spread that Hash as keyword arguments by passing it to the `send` method using the double-splat opertator (`**`). For example:
|
|
591
|
-
|
|
592
|
-
```ruby
|
|
593
|
-
message = {
|
|
594
|
-
to: '447700900000',
|
|
595
|
-
from: '447700900001',
|
|
596
|
-
channel: 'mms',
|
|
597
|
-
message_type: 'image',
|
|
598
|
-
image: {
|
|
599
|
-
url: 'https://example.com/image.jpg',
|
|
600
|
-
caption: 'This is an image'
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
response = client.messaging.send(**message)
|
|
605
|
-
```
|
|
606
|
-
|
|
607
|
-
**Using a Combination of Keyword Arguments and Spread**
|
|
608
|
-
|
|
609
|
-
You can use a combination of the above two approaches. This might be useful in situations where you want to iteratively send the same message to multiple recipients, for example:
|
|
610
|
-
|
|
611
|
-
```ruby
|
|
612
|
-
message = {
|
|
613
|
-
from: '447700900000',
|
|
614
|
-
channel: 'sms',
|
|
615
|
-
message_type: 'text',
|
|
616
|
-
text: 'Hello world!'
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
['447700900001', '447700900002', '447700900003'].each do |to_number|
|
|
620
|
-
client.messaging.send(to: to_number, **message)
|
|
621
|
-
end
|
|
622
|
-
```
|
|
623
|
-
|
|
624
|
-
**Using Channel Convenience Methods**
|
|
625
|
-
|
|
626
|
-
The Ruby SDK provides convenience methods for each channel which return a Hash object which you can then pass to the `send` method in the same way that you would with a Hash literal. As well as a simpler interface, the convenience methods also provide some basic validation.
|
|
627
|
-
|
|
628
|
-
Other than SMS (which has only one type -- `text`), these methods require a `:type` argument, which defines the `message_type` of the message within that channel. They also require a `:message` argument, which defvines the message itself; this is a String in the case of `text` messages, and a Hash containing the appopriate properties for other message types (e.g. `image`). You can also optionally pass an `opts` arguments, the value of which should be a Hash which defines any other property that you want to include in the message.
|
|
629
|
-
|
|
630
|
-
```ruby
|
|
631
|
-
# Using the SMS method like this:
|
|
632
|
-
message = client.messaging.sms(to: "447700900000", from: "447700900001", message: "Hello world!")
|
|
633
|
-
|
|
634
|
-
# is the equivalent of using a Hash literal like this:
|
|
635
|
-
message = {
|
|
636
|
-
channel: "sms",
|
|
637
|
-
to: "447700900000",
|
|
638
|
-
from: "447700900001",
|
|
639
|
-
message_type: "text",
|
|
640
|
-
text: "Hello world!"
|
|
641
|
-
}
|
|
642
|
-
```
|
|
643
|
-
|
|
644
|
-
Once the message Hash is created, you can then pass it into the `send` method using the double-splat opertator (`**`).
|
|
645
|
-
|
|
646
|
-
```ruby
|
|
647
|
-
response = client.messaging.send(**message)
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
A few additional examples of using these convenience methods are shown below:
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
```ruby
|
|
654
|
-
# creating an RCS Text message
|
|
655
|
-
message = client.messaging.rcs(to: "447700900000", from: "RCS-Agent", type: 'text', message: 'Hello world!')
|
|
656
|
-
|
|
657
|
-
# creating a WhatsApp Text message
|
|
658
|
-
message = client.messaging.whatsapp(to: "447700900000", from: "447700900001", type: 'text', message: 'Hello world!')
|
|
659
|
-
|
|
660
|
-
# creating a WhatsApp Image message
|
|
661
|
-
message = client.messaging.whatsapp(to: "447700900000", from: "447700900001", type: 'image', message: { url: 'https://example.com/image.jpg' })
|
|
662
|
-
|
|
663
|
-
# creating an MMS audio message with optional properties
|
|
664
|
-
message = client.messaging.mms(
|
|
665
|
-
to: "447700900000",
|
|
666
|
-
from: "447700900001",
|
|
667
|
-
type: 'audio',
|
|
668
|
-
message: {
|
|
669
|
-
url: 'https://example.com/audio.mp3'
|
|
670
|
-
},
|
|
671
|
-
opts: {
|
|
672
|
-
client_ref: "abc123"
|
|
673
|
-
}
|
|
674
|
-
)
|
|
675
|
-
```
|
|
676
|
-
|
|
677
|
-
You can choose to omit the `to` and/or `from` arguments from the convenience method calls and instead pass them in as keyword arguments during the `send` method invocation.
|
|
678
|
-
|
|
679
|
-
```ruby
|
|
680
|
-
message = client.messaging.sms(from: "447700900001", message: "Hello world!")
|
|
681
|
-
|
|
682
|
-
['447700900001', '447700900002', '447700900003'].each do |to_number|
|
|
683
|
-
client.messaging.send(to: to_number, **message)
|
|
684
|
-
end
|
|
685
|
-
```
|
|
686
|
-
|
|
687
|
-
### Sending a Message with Failover
|
|
688
|
-
|
|
689
|
-
The Messages API lets you define one or more failover messages which will be sent if the initial message is rejected. In the Ruby SDK, this feature is implemented by passing a `failover` keyword argument during the invocation of the `send` method. The value of this argument must be an Array containing one or more Hash objects representing the failover message(s). For example:
|
|
690
|
-
|
|
691
|
-
```ruby
|
|
692
|
-
# Sending an RCS message with failover to SMS
|
|
693
|
-
rcs_message = messaging.rcs(
|
|
694
|
-
to: '447900000000',
|
|
695
|
-
from: 'RCS-Agent',
|
|
696
|
-
type: 'text',
|
|
697
|
-
message: 'This is an RCS message. If you see this, RCS is working!'
|
|
698
|
-
)
|
|
699
|
-
|
|
700
|
-
sms_message = messaging.sms(
|
|
701
|
-
to: '447900000000',
|
|
702
|
-
from: 'Vonage',
|
|
703
|
-
message: 'This is a failover SMS message in case RCS fails.'
|
|
704
|
-
)
|
|
705
|
-
|
|
706
|
-
response = messaging.send(**rcs_message, failover: [sms_message])
|
|
707
|
-
```
|
|
708
|
-
|
|
709
|
-
## Verify API v2
|
|
710
|
-
|
|
711
|
-
The [Vonage Verify API v2](https://developer.vonage.com/en/verify/verify-v2/overview) allows you to manage 2FA verification workflows over a number of different channels such as SMS, WhatsApp, WhatsApp Interactive, Voice, Email, and Silent Authentication, either individually or in combination with each other. See the Vonage Developer Documentation for a [complete API reference](https://developer.vonage.com/en/api/verify.v2) listing all the channels, verification options, and callback types.
|
|
712
|
-
|
|
713
|
-
The Ruby SDK provides two methods for interacting with the Verify v2 API:
|
|
714
|
-
|
|
715
|
-
- `Verify2#start_verification`: starts a new verification request. Here you can specify options for the request and the workflow to be used.
|
|
716
|
-
- `Verify2#check_code`: for channels where the end-user is sent a one-time code, this method is used to verify the code against the `request_id` of the verification request created by the `start_verification` method.
|
|
717
|
-
|
|
718
|
-
### Creating a Verify2 Object
|
|
719
|
-
|
|
720
|
-
```ruby
|
|
721
|
-
verify = client.verify2
|
|
722
|
-
```
|
|
723
|
-
|
|
724
|
-
### Making a verification request
|
|
725
|
-
|
|
726
|
-
For simple requests, you may prefer to manually set the value for `workflow` (an array of one or more hashes containing the settings for a particular channel) and any optional params.
|
|
727
|
-
|
|
728
|
-
Example with the required `:brand` and `:workflow` arguments:
|
|
729
|
-
|
|
730
|
-
```ruby
|
|
731
|
-
verification_request = verify.start_verification(
|
|
732
|
-
brand: 'Acme',
|
|
733
|
-
workflow: [{channel: 'sms', to: '447000000000'}]
|
|
734
|
-
)
|
|
735
|
-
```
|
|
736
|
-
|
|
737
|
-
Example with the required `:brand` and `:workflow` arguments, and an optional `code_length`:
|
|
738
|
-
|
|
739
|
-
```ruby
|
|
740
|
-
verification_request = verify.start_verification(
|
|
741
|
-
brand: 'Acme',
|
|
742
|
-
workflow: [{channel: 'sms', to: '447000000000'}],
|
|
743
|
-
code_length: 6
|
|
744
|
-
)
|
|
745
|
-
```
|
|
746
|
-
|
|
747
|
-
For more complex requests (e.g. with mutliple workflow channels or addtional options), or to take advantage of built-in input validation, you can use the `StartVerificationOptions` object and the `Workflow` and various channel objects or the `WorkflowBuilder`:
|
|
748
|
-
|
|
749
|
-
#### Create options using StartVerificationOptions object
|
|
750
|
-
|
|
751
|
-
```ruby
|
|
752
|
-
opts = verify.start_verification_options(
|
|
753
|
-
locale: 'fr-fr',
|
|
754
|
-
code_length: 6,
|
|
755
|
-
client_ref: 'abc-123'
|
|
756
|
-
).to_h
|
|
757
|
-
|
|
758
|
-
verification_request = verify.start_verification(
|
|
759
|
-
brand: 'Acme',
|
|
760
|
-
workflow: [{channel: 'email', to: 'alice.example.com'}],
|
|
761
|
-
**opts
|
|
762
|
-
)
|
|
763
|
-
```
|
|
764
|
-
|
|
765
|
-
#### Create workflow using Workflow and Channel objects
|
|
766
|
-
|
|
767
|
-
```ruby
|
|
768
|
-
# Instantiate a Workflow object
|
|
769
|
-
workflow = verify.workflow
|
|
770
|
-
|
|
771
|
-
# Add channels to the workflow
|
|
772
|
-
workflow << workflow.sms(to: '447000000000')
|
|
773
|
-
workflow << workflow.email(to: 'alice.example.com')
|
|
774
|
-
|
|
775
|
-
# Channel data is encpsulated in channel objects stored in the Workflow list array
|
|
776
|
-
workflow.list
|
|
777
|
-
# => [ #<Vonage::Verify2::Channels::SMS:0x0000561474a74778 @channel="sms", @to="447000000000">,
|
|
778
|
-
#<Vonage::Verify2::Channels::Email:0x0000561474c51a28 @channel="email", @to="alice.example.com">]
|
|
779
|
-
|
|
780
|
-
# To use the list as the value for `:workflow` in a `start_verification` request call,
|
|
781
|
-
# the objects must be hashified
|
|
782
|
-
workflow_list = workflow.hashified_list
|
|
783
|
-
# => [{:channel=>"sms", :to=>"447000000000"}, {:channel=>"email", :to=>"alice.example.com"}]
|
|
784
|
-
|
|
785
|
-
verification_request = verify.start_verification(brand: 'Acme', workflow: workflow_list)
|
|
786
|
-
```
|
|
787
|
-
|
|
788
|
-
#### Create a workflow using the WorkflowBuilder
|
|
789
|
-
|
|
790
|
-
```ruby
|
|
791
|
-
workflow = verify.workflow_builder.build do |builder|
|
|
792
|
-
builder.add_voice(to: '447000000001')
|
|
793
|
-
builder.add_whatsapp(to: '447000000000')
|
|
794
|
-
end
|
|
795
|
-
|
|
796
|
-
workflow_list = workflow.hashified_list
|
|
797
|
-
# => [{:channel=>"voice", :to=>"447000000001"}, {:channel=>"whatsapp", :to=>"447000000000"}]
|
|
798
|
-
|
|
799
|
-
verification_request = verify.start_verification(brand: 'Acme', workflow: workflow_list)
|
|
800
|
-
```
|
|
801
|
-
|
|
802
|
-
### Cancelling a request
|
|
803
|
-
|
|
804
|
-
You can cancel in in-progress verification request
|
|
805
|
-
|
|
806
|
-
```ruby
|
|
807
|
-
# Get the `request_id` from the Vonage#Response object returned by the `start_verification` method call
|
|
808
|
-
request_id = verification_request.request_id
|
|
809
|
-
|
|
810
|
-
verify.cancel_verification_request(request_id: request_id)
|
|
811
|
-
```
|
|
812
|
-
|
|
813
|
-
### Checking a code
|
|
814
|
-
|
|
815
|
-
```ruby
|
|
816
|
-
# Get the `request_id` from the Vonage#Response object returned by the `start_verification` method call
|
|
817
|
-
request_id = verification_request.request_id
|
|
818
|
-
|
|
819
|
-
# Get the one-time code via user input
|
|
820
|
-
# e.g. from params in a route handler or controller action for a form input
|
|
821
|
-
code = params[:code]
|
|
822
|
-
|
|
823
|
-
begin
|
|
824
|
-
code_check = verify.check_code(request_id: request_id, code: code)
|
|
825
|
-
rescue => error
|
|
826
|
-
# an invalid code will raise an exception of type Vonage::ClientError
|
|
827
|
-
end
|
|
828
|
-
|
|
829
|
-
if code_check.http_response.code == '200'
|
|
830
|
-
# code is valid
|
|
831
|
-
end
|
|
832
|
-
```
|
|
833
|
-
|
|
834
|
-
### Working with Verify Custom Templates and Template Fragments
|
|
835
|
-
|
|
836
|
-
Verify custom templates allow you to customize the message sent to deliver an OTP to your users, rather than using the default Vonage templates. See the [Template Management Guide document](https://developer.vonage.com/en/verify/guides/custom-templates) for more information.
|
|
837
|
-
|
|
838
|
-
#### Templates
|
|
839
|
-
|
|
840
|
-
```ruby
|
|
841
|
-
# Get a list of all templates
|
|
842
|
-
template_list = verify.templates.list
|
|
843
|
-
|
|
844
|
-
# Get details of a specific template
|
|
845
|
-
template = verify.templates.info(template_id: '8f35a1a7-eb2f-4552-8fdf-fffdaee41bc9')
|
|
846
|
-
|
|
847
|
-
# Create a new template
|
|
848
|
-
verify.templates.create(name: 'my-template')
|
|
849
|
-
|
|
850
|
-
# Update an existing template
|
|
851
|
-
verify.templates.update(
|
|
852
|
-
template_id: '8f35a1a7-eb2f-4552-8fdf-fffdaee41bc9',
|
|
853
|
-
name: 'my-updated-template'
|
|
854
|
-
)
|
|
855
|
-
|
|
856
|
-
# Delete a template
|
|
857
|
-
verify.templates.delete(template_id: '8f35a1a7-eb2f-4552-8fdf-fffdaee41bc9')
|
|
858
|
-
```
|
|
859
|
-
|
|
860
|
-
#### Template Fragments
|
|
861
|
-
|
|
862
|
-
```ruby
|
|
863
|
-
# Get a list of template fragments for a specific template
|
|
864
|
-
template_fragment_list = verify.template_fragments.list(template_id: '8f35a1a7-eb2f-4552-8fdf-fffdaee41bc9')
|
|
865
|
-
|
|
866
|
-
# Get details of a specific template fragment
|
|
867
|
-
template_fragment = verify.template_fragments.info(
|
|
868
|
-
template_id: '8f35a1a7-eb2f-4552-8fdf-fffdaee41bc9',
|
|
869
|
-
template_fragment_id: 'c70f446e-997a-4313-a081-60a02a31dc19'
|
|
870
|
-
)
|
|
871
|
-
|
|
872
|
-
# Create a new template fragement
|
|
873
|
-
verify.template_fragments.create(
|
|
874
|
-
template_id: '8f35a1a7-eb2f-4552-8fdf-fffdaee41bc9',
|
|
875
|
-
channel: 'sms',
|
|
876
|
-
locale: 'en-gb',
|
|
877
|
-
text: 'Your code is: ${code}'
|
|
878
|
-
)
|
|
879
|
-
|
|
880
|
-
# Update an existing template fragment
|
|
881
|
-
verify.template_fragments.update(
|
|
882
|
-
template_id: '8f35a1a7-eb2f-4552-8fdf-fffdaee41bc9',
|
|
883
|
-
template_fragment_id: 'c70f446e-997a-4313-a081-60a02a31dc1',
|
|
884
|
-
text: 'Your one-time code is: ${code}'
|
|
885
|
-
)
|
|
886
|
-
|
|
887
|
-
# Delete a template fragment
|
|
888
|
-
verify.template_fragments.delete(
|
|
889
|
-
template_id: '8f35a1a7-eb2f-4552-8fdf-fffdaee41bc9',
|
|
890
|
-
template_fragment_id: 'c70f446e-997a-4313-a081-60a02a31dc19'
|
|
891
|
-
)
|
|
892
|
-
```
|
|
893
|
-
|
|
894
|
-
## Voice API
|
|
895
|
-
|
|
896
|
-
The [Vonage Voice API](The [Vonage Verify API v2](https://developer.vonage.com/en/verify/verify-v2/overview) allows you to automate voice interactions by creating calls, streaming audio, playing text to speech, playing DTMF tones, and other actions. See the Vonage Developer Documentation for a [complete API reference](https://developer.vonage.com/en/api/voice) listing all the Voice API capabilities.
|
|
897
|
-
|
|
898
|
-
The Ruby SDK provides numerous methods for interacting with the Voice v2 API. Here's an example of using the `create` method to make an outbound text-to-speech call:
|
|
899
|
-
|
|
900
|
-
```ruby
|
|
901
|
-
response = client.voice.create(
|
|
902
|
-
to: [{
|
|
903
|
-
type: 'phone',
|
|
904
|
-
number: '447700900000'
|
|
905
|
-
}],
|
|
906
|
-
from: {
|
|
907
|
-
type: 'phone',
|
|
908
|
-
number: '447700900001'
|
|
909
|
-
},
|
|
910
|
-
answer_url: [
|
|
911
|
-
'https://raw.githubusercontent.com/nexmo-community/ncco-examples/gh-pages/text-to-speech.json'
|
|
912
|
-
]
|
|
913
|
-
)
|
|
914
|
-
```
|
|
915
|
-
|
|
916
|
-
### NCCO Builder
|
|
171
|
+
## NCCO Builder
|
|
917
172
|
|
|
918
173
|
The Vonage Voice API accepts instructions via JSON objects called NCCOs. Each NCCO can be made up multiple actions that are executed in the order they are written. The Vonage API Developer Portal contains an [NCCO Reference](https://developer.vonage.com/voice/voice-api/ncco-reference) with instructions and information on all the parameters possible.
|
|
919
174
|
|
|
@@ -939,103 +194,65 @@ response = client.voice.create({
|
|
|
939
194
|
})
|
|
940
195
|
```
|
|
941
196
|
|
|
942
|
-
##
|
|
943
|
-
|
|
944
|
-
The [Vonage Identity Insights API](https://developer.vonage.com/en/identity-insights/overview) provides real-time access to a broad range of attributes related to the carrier, subscriber, or device associated with a phone number. See the Vonage Developer Documentation for a [complete API reference](https://developer.vonage.com/en/api/identity-insights) listing all available insight types.
|
|
945
|
-
|
|
946
|
-
> [!NOTE]
|
|
947
|
-
> The Vonage Ruby SDK currently supports the following insight types:
|
|
948
|
-
> - Format
|
|
949
|
-
> - Current Carrier
|
|
950
|
-
> - Original Carrier
|
|
951
|
-
> - SIM Swap
|
|
952
|
-
|
|
953
|
-
Calling `identity_insights` on an instance of `Client` returns an `IdentityInsights` object which provides methods for interacting with the Identity Insights API.
|
|
954
|
-
|
|
955
|
-
```ruby
|
|
956
|
-
client.identity_insights # => #<Vonage::IdentityInsights>
|
|
957
|
-
```
|
|
958
|
-
|
|
959
|
-
### Making an Insights Request
|
|
960
|
-
|
|
961
|
-
You can make an Identity Insights request by calling the `IdentityInsights#requests` method, for example:
|
|
962
|
-
|
|
963
|
-
```ruby
|
|
964
|
-
response = client.identity_insights.requests(phone_number: '447900000000', insights: { format: {} })
|
|
965
|
-
```
|
|
197
|
+
## Messages API
|
|
966
198
|
|
|
967
|
-
|
|
199
|
+
The [Vonage Messages API](https://developer.vonage.com/messages/overview) allows you to send messages over a number of different channels, and various message types within each channel. See the Vonage Developer Documentation for a [complete API reference](https://developer.vonage.com/api/messages-olympus) listing all the channel and message type combinations.
|
|
968
200
|
|
|
969
|
-
The
|
|
201
|
+
The Ruby SDK allows you to construct message data for specific messaging channels. Other than SMS (which has only one type -- text), you need to pass the message `:type` as well as the `:message` itself as arguments to the appropriate messages method, along with any optional properties if needed.
|
|
970
202
|
|
|
971
203
|
```ruby
|
|
972
|
-
|
|
973
|
-
|
|
204
|
+
# creating an SMS message
|
|
205
|
+
message = Vonage::Messaging::Message.sms(message: 'Hello world!')
|
|
974
206
|
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
```ruby
|
|
978
|
-
insights_builder.add_format.add_current_carrier
|
|
979
|
-
# => #<Vonage::IdentityInsights::InsightsBuilder @insights={:format=>{}, :current_carrier=>{}}>
|
|
980
|
-
```
|
|
207
|
+
# creating a WhatsApp Text message
|
|
208
|
+
message = Vonage::Messaging::Message.whatsapp(type: 'text', message: 'Hello world!')
|
|
981
209
|
|
|
982
|
-
|
|
210
|
+
# creating a WhatsApp Image message
|
|
211
|
+
message = Vonage::Messaging::Message.whatsapp(type: 'image', message: { url: 'https://example.com/image.jpg' })
|
|
983
212
|
|
|
984
|
-
|
|
985
|
-
|
|
213
|
+
# creating an MMS audio message with optional properties
|
|
214
|
+
message = Vonage::Messaging::Message.mms(type: 'audio', message: { url: 'https://example.com/audio.mp3' }, opts: {client_ref: "abc123"})
|
|
986
215
|
```
|
|
987
216
|
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
The `IdentityInsights#requests` method can also be called with a block. The method yields an `InsightsBuilder` object to the block and expects an `InsightsBuilder` object to be returned by the block.
|
|
217
|
+
Once the message data is created, you can then send the message.
|
|
991
218
|
|
|
992
219
|
```ruby
|
|
993
|
-
response = client.
|
|
994
|
-
builder.add_format
|
|
995
|
-
.add_original_carrier
|
|
996
|
-
.add_current_carrier
|
|
997
|
-
.add_sim_swap(period: 2400)
|
|
998
|
-
end
|
|
220
|
+
response = client.messaging.send(to: "447700900000", from: "447700900001", **message)
|
|
999
221
|
```
|
|
1000
222
|
|
|
1001
|
-
> [!NOTE]
|
|
1002
|
-
> When requesting the SIM Swap insight, you should pass the `purpose` keyword argument to the `IdentityInsights#requests` method invocation with a value of `'FraudPreventionAndDetection'`.
|
|
1003
|
-
|
|
1004
223
|
## Documentation
|
|
1005
224
|
|
|
1006
|
-
Vonage Ruby
|
|
225
|
+
Vonage Ruby documentation: https://www.rubydoc.info/github/Vonage/vonage-ruby-sdk
|
|
1007
226
|
|
|
1008
|
-
Vonage Ruby
|
|
227
|
+
Vonage Ruby code examples: https://github.com/Nexmo/nexmo-ruby-code-snippets
|
|
1009
228
|
|
|
1010
|
-
Vonage APIs API reference: https://developer.
|
|
229
|
+
Vonage APIs API reference: https://developer.nexmo.com/api
|
|
1011
230
|
|
|
1012
|
-
##
|
|
1013
|
-
|
|
1014
|
-
The following is a list of Vonage APIs for which the Ruby SDK currently provides support:
|
|
1015
|
-
|
|
1016
|
-
* [Account API](https://developer.vonage.com/en/account/overview)
|
|
1017
|
-
* [Application API](https://developer.vonage.com/en/application/overview)
|
|
1018
|
-
* [Conversation API](https://developer.vonage.com/en/conversation/overview)
|
|
1019
|
-
* [Identity Insights API](https://developer.vonage.com/en/identity-insights/overview)
|
|
1020
|
-
* [Meetings API](https://developer.vonage.com/en/meetings/overview) (deprecated)
|
|
1021
|
-
* [Messages API](https://developer.vonage.com/en/messages/overview)
|
|
1022
|
-
* [Network Number Verification API](https://developer.vonage.com/en/number-verification/overview) (deprecated)
|
|
1023
|
-
* [Network SIM Swap API](https://developer.vonage.com/en/sim-swap/overview) (deprecated)
|
|
1024
|
-
* [Number Insight API](https://developer.vonage.com/en/number-insight/overview)
|
|
1025
|
-
* [Numbers API](https://developer.vonage.com/en/numbers/overview)
|
|
1026
|
-
* [Proactive Connect API](https://developer.vonage.com/en/proactive-connect/overview) *
|
|
1027
|
-
* [Redact API](https://developer.vonage.com/en/redact/overview)
|
|
1028
|
-
* [SMS API](https://developer.vonage.com/en/messaging/sms/overview)
|
|
1029
|
-
* [Subaccounts API](https://developer.vonage.com/en/account/subaccounts/overview)
|
|
1030
|
-
* [Verify API](https://developer.vonage.com/en/verify/overview)
|
|
1031
|
-
* [Voice API](https://developer.vonage.com/en/verify/overview)
|
|
1032
|
-
|
|
1033
|
-
\* The Proactive Connect API is partially supported in the SDK. Specifically, the Events, Items, and Lists endpoints are supported.
|
|
1034
|
-
|
|
1035
|
-
## Other SDKs and Tools
|
|
231
|
+
## Frequently Asked Questions
|
|
1036
232
|
|
|
1037
|
-
|
|
233
|
+
## Supported APIs
|
|
1038
234
|
|
|
235
|
+
The following is a list of Vonage APIs and whether the Ruby SDK provides support for them:
|
|
236
|
+
|
|
237
|
+
| API | API Release Status | Supported?
|
|
238
|
+
|----------|:---------:|:-------------:|
|
|
239
|
+
| Account API | General Availability |✅|
|
|
240
|
+
| Alerts API | General Availability |✅|
|
|
241
|
+
| Application API | General Availability |✅|
|
|
242
|
+
| Audit API | Beta |❌|
|
|
243
|
+
| Conversation API | Beta |❌|
|
|
244
|
+
| Dispatch API | Beta |❌|
|
|
245
|
+
| External Accounts API | Beta |❌|
|
|
246
|
+
| Media API | Beta | ❌|
|
|
247
|
+
| Messages API | General Availability |✅|
|
|
248
|
+
| Number Insight API | General Availability |✅|
|
|
249
|
+
| Number Management API | General Availability |✅|
|
|
250
|
+
| Pricing API | General Availability |✅|
|
|
251
|
+
| Redact API | Developer Preview |✅|
|
|
252
|
+
| Reports API | Beta |❌|
|
|
253
|
+
| SMS API | General Availability |✅|
|
|
254
|
+
| Verify API | General Availability |✅|
|
|
255
|
+
| Voice API | General Availability |✅|
|
|
1039
256
|
|
|
1040
257
|
## License
|
|
1041
258
|
|
|
@@ -1043,13 +260,3 @@ This library is released under the [Apache 2.0 License][license]
|
|
|
1043
260
|
|
|
1044
261
|
[signup]: https://dashboard.nexmo.com/sign-up?utm_source=DEV_REL&utm_medium=github&utm_campaign=ruby-client-library
|
|
1045
262
|
[license]: LICENSE.txt
|
|
1046
|
-
|
|
1047
|
-
## Contribute!
|
|
1048
|
-
|
|
1049
|
-
_We :heart: contributions to this library!_
|
|
1050
|
-
|
|
1051
|
-
It is a good idea to [talk to us](https://developer.vonage.com/community/slack)
|
|
1052
|
-
first if you plan to add any new functionality.
|
|
1053
|
-
Otherwise, [bug reports](https://github.com/Vonage/vonage-ruby-sdk/issues),
|
|
1054
|
-
[bug fixes](https://github.com/Vonage/vonage-ruby-sdk/pulls) and feedback on the
|
|
1055
|
-
library are always appreciated.
|