PHPackages                             vonage/client-core - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. vonage/client-core

ActiveLibrary[API Development](/categories/api)

vonage/client-core
==================

PHP Client for using Vonage's API.

4.12.0(4mo ago)9288.8M—6.1%179[2 issues](https://github.com/Vonage/vonage-php-sdk-core/issues)[1 PRs](https://github.com/Vonage/vonage-php-sdk-core/pulls)16Apache-2.0PHPPHP ~8.1 || ~8.2 || ~8.3 || ~8.4 || ~8.5CI failing

Since May 1Pushed 1mo ago31 watchersCompare

[ Source](https://github.com/Vonage/vonage-php-sdk-core)[ Packagist](https://packagist.org/packages/vonage/client-core)[ Docs](https://developer.vonage.com)[ RSS](/packages/vonage-client-core/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (17)Versions (153)Used By (16)

Client Library for PHP
======================

[](#client-library-for-php)

[![Contributor Covenant](https://camo.githubusercontent.com/2757a9db291c5ceda172e31d4fa5f3c4048a6e6257ee0b7113f80de277074b91/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436f6e7472696275746f72253230436f76656e616e742d76322e3025323061646f707465642d6666363962342e737667)](CODE_OF_CONDUCT.md)[![Build Status](https://github.com/vonage/vonage-php-sdk-core/workflows/build/badge.svg)](https://github.com/Vonage/vonage-php-sdk-core/actions?query=workflow%3Abuild)[![Latest Stable Version](https://camo.githubusercontent.com/ac9a6b55db6a678777bbf8355912cd62b6fc41b48c195b8d2ab0af1bec6a5a2f/68747470733a2f2f706f7365722e707567782e6f72672f766f6e6167652f636c69656e742f762f737461626c65)](https://packagist.org/packages/vonage/client)[![License](https://camo.githubusercontent.com/5b60841bea9e11d9d0b0950d690c9bc554e06385634056a7d5d62a15d1a4eabe/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4170616368655f322e302d626c75652e737667)](https://opensource.org/licenses/Apache-2.0)

[![The Vonage logo](./vonage_logo.png)](./vonage_logo.png)

*This library requires a minimum PHP version of 8.1*

This is the PHP client library for use Vonage's API. To use this, you'll need a Vonage account. [Sign up for free here](https://ui.idp.vonage.com/ui/auth/registration).

- [Installation](#installation)
- [Usage](#usage)
- [Examples](#examples)
- [Test Suite](#test-suite)
- [Contributing](#contributing)

Installation
------------

[](#installation)

To use the client library you'll need to have [created a Vonage account](https://dashboard.nexmo.com/sign-up?utm_source=DEV_REL&utm_medium=github&utm_campaign=php-client-library).

To install the PHP client library to your project, we recommend using [Composer](https://getcomposer.org/).

```
composer require vonage/client
```

> Note that this actually points to a wrapper library that includes an HTTP client -and- this core library. You can install this library directly from Composer if you wish, with the ability to choose the HTTP client your project uses.

> You don't need to clone this repository to use this library in your own projects. Use Composer to install it from Packagist.

If you're new to Composer, here are some resources that you may find useful:

- [Composer's Getting Started page](https://getcomposer.org/doc/00-intro.md) from Composer project's documentation.
- [A Beginner's Guide to Composer](https://scotch.io/tutorials/a-beginners-guide-to-composer) from the good people at ScotchBox.

Usage
-----

[](#usage)

If you're using Composer, make sure the autoloader is included in your project's bootstrap file:

```
require_once "vendor/autoload.php";
```

Create a client with your API key and secret:

```
$client = new Vonage\Client(new Vonage\Client\Credentials\Basic(API_KEY, API_SECRET));
```

For testing purposes you may want to change the URL that `vonage/client` makes requests to from `api.vonage.com` to something else. You can do this by providing an array containing `base_api_url` as the second parameter when creating a `Vonage\Client` instance.

```
$client = new Vonage\Client(
    new Vonage\Client\Credentials\Basic(API_KEY, API_SECRET),
    [
        'base_api_url' => 'https://example.com'
    ]
);
```

For APIs that would usually hit `rest.nexmo.com`, supplying a `base_rest_url` as an option to the constructor will change those requests.

Examples
--------

[](#examples)

### Sending a Message via the SMS API

[](#sending-a-message-via-the-sms-api)

To use [Vonage's SMS API](https://developer.nexmo.com/messaging/sms/overview) to send an SMS message, call the `$client->sms()->send()` method.

**A message object** is used to create the SMS messages. Each message type can be constructed with the required parameters, and a fluent interface provides access to optional parameters.

```
$text = new \Vonage\SMS\Message\SMS(VONAGE_TO, VONAGE_FROM, 'Test message using PHP client library');
$text->setClientRef('test-message');
```

The message object is passed to the `send` method:

```
$response = $client->sms()->send($text);
```

Once sent, the message object can be used to access the response data.

```
$data = $response->current();
echo "Sent message to " . $data->getTo() . ". Balance is now " . $data->getRemainingBalance() . PHP_EOL;
```

Since each SMS message can be split into multiple messages, the response contains an object for each message that was generated. You can check to see how many messages were generated using the standard `count()` function in PHP. If you want to get the first message, you can use the `current()` method on the response.

```
$data = $response->current();
$data->getRemainingBalance();
foreach($response as $index => $data){
    $data->getRemainingBalance();
}
```

The [send example](https://github.com/Vonage/vonage-php-code-snippets/blob/master/sms/send-sms.php) also has full working examples.

### Detecting Encoding Type

[](#detecting-encoding-type)

You can use a static `isGsm7()` method within the SMS Client code to determine whether to send the message using GSM-7 encoding or Unicode. Here is an example:

```
$sms = new \Vonage\SMS\Message\SMS('123', '456', 'is this gsm7?');

if (Vonage\SMS\Message\SMS::isGsm7($text)) {
    $sms->setType('text');
} else {
    $sms->setType('unicode');
}
```

### Receiving a Message

[](#receiving-a-message)

Inbound messages are [sent to your application as a webhook](https://developer.nexmo.com/messaging/sms/guides/inbound-sms). The Client library provides a way to create an inbound message object from a webhook:

```
try {
    $inbound = \Vonage\SMS\Webhook\Factory::createFromGlobals();
    error_log($inbound->getText());
} catch (\InvalidArgumentException $e) {
    error_log('invalid message');
}
```

### Signing a Message

[](#signing-a-message)

*You may also like to read the [documentation about message signing](https://developer.nexmo.com/concepts/guides/signing-messages).*

The SMS API supports the ability to sign messages by generating and adding a signature using a "Signature Secret" rather than your API secret. The algorithms supported are:

- `md5hash1`
- `md5`
- `sha1`
- `sha256`
- `sha512`

Both your application and Vonage need to agree on which algorithm is used. In the [dashboard](https://dashboard.nexmo.com), visit your account settings page and under "API Settings" you can select the algorithm to use. This is also the location where you will find your "Signature Secret" (it's different from the API secret).

Create a client using these credentials, and the algorithm to use, for example:

```
$client = new Vonage\Client(new Vonage\Client\Credentials\SignatureSecret(API_KEY, SIGNATURE_SECRET, 'sha256'));
```

Using this client, your SMS API messages will be sent as signed messages.

### Verifying an Incoming Message Signature

[](#verifying-an-incoming-message-signature)

*You may also like to read the [documentation about message signing](https://developer.nexmo.com/concepts/guides/signing-messages).*

If you have message signing enabled for incoming messages, the SMS webhook will include the fields `sig`, `nonce` and `timestamp`. To verify the signature is from Vonage, you create a Signature object using the incoming data, your signature secret and the signature method. Then use the `check()` method with the actual signature that was received (usually `_GET['sig']`) to make sure, that it is correct.

```
$signature = new \Vonage\Client\Signature($_GET, SIGNATURE_SECRET, 'sha256');

// is it valid? Will be true or false
$isValid = $signature->check($_GET['sig']);
```

Using your signature secret and the other supplied parameters, the signature can be calculated and checked against the incoming signature value.

### Sending a Message via. the Messages API

[](#sending-a-message-via-the-messages-api)

The [Messages API](https://developer.vonage.com/api/messages-olympus) is used to send a variety of outbound messages. The following platforms are currently supported:

- **SMS**
- **MMS**
- **WhatsApp**
- **Messenger**
- **Viber**

Each one of these platforms has a different category of message you can send (for example, with WhatsApp you can send text, an image, audio, video, a file or a template but for Viber you can only send a text or an image). You can find all the sendable message types under the namespace `\Vonage\Messages\Channel`. The reason each type is separated out this way is that the platform and message type requires different parameters in the API call.

The `\Vonage\Messages\Client` is configured in a similar way to the SMS API Client. The difference is that the authentication can be either a JSON Web Token (JWT) or Basic Authentication. You can find more info on how to set up your Client's credentials under the 'Usage' section of this ReadMe.

Here some examples:

### Sending a WhatsApp Text

[](#sending-a-whatsapp-text)

First, we need to create a new WhatsAppText object like so:

```
$whatsAppText = new Vonage\Messages\Channel\WhatsApp\WhatsAppText(
    FROM_NUMBER,
    TO_NUMBER,
    'this is a WA text from vonage'
);
```

The Messages API Client has one method, `send()` where you can send any of the message types provided. So, to send this message, the following code will do that, assuming you have already set up your Vonage client correctly:

```
$client->messages()->send($whatsAppText);
```

Your response will be a JSON payload if the error range is with 200, or will throw a relevant `APIException` if it's within 400/500.

### Send a Viber Image

[](#send-a-viber-image)

Some `Channel` objects require more arguments in order to be created. You can see the rough mapping of these requirements by comparing the constructor arguments vs. the API Documentation. Some of these messages take custom reusable objects (that are under the `\Vonage\Messages\MessageObjects` namespace). One of these is an image - so here is an example of how to send a Viber Image:

```
$imageObject = Vonage\Messages\MessageObjects\ImageObject(
    'https://picsum.photos/200/300',
    'image caption'
);

$viberImage = new Vonage\Messages\Channel\Viber\ViberImage(
    FROM_NUMBER,
    TO_NUMBER,
    $imageObject
);

$client->messages()->send($viberImage);
```

### Verify Examples (v1)

[](#verify-examples-v1)

#### Starting a Verification

[](#starting-a-verification)

Vonage's [Verify API](https://developer.nexmo.com/verify/overview) makes it easy to prove that a user has provided their own phone number during signup, or implement second factor authentication during sign in.

You can start a verification process using code like this:

```
$request = new \Vonage\Verify\Request('14845551212', 'My App');
$response = $client->verify()->start($request);
echo "Started verification with an id of: " . $response->getRequestId();
```

Once the user inputs the pin code they received, call the `check()` method (see below) with the request ID and the PIN to confirm the PIN is correct.

#### Controlling a Verification

[](#controlling-a-verification)

To cancel an in-progress verification, or to trigger the next attempt to send the confirmation code, you can pass either an existing verification object to the client library, or simply use a request ID:

```
$client->verify()->trigger('00e6c3377e5348cdaf567e1417c707a5');
$client->verify()->cancel('00e6c3377e5348cdaf567e1417c707a5');
```

#### Checking a Verification

[](#checking-a-verification)

In the same way, checking a verification requires the PIN the user provided, and the request ID:

```
try {
    $client->verify()->check('00e6c3377e5348cdaf567e1417c707a5', '1234');
    echo "Verification was successful (status: " . $verification->getStatus() . ")\n";
} catch (Exception $e) {
    echo "Verification failed with status " . $e->getCode()
        . " and error text \"" . $e->getMessage() . "\"\n";
}
```

#### Searching For a Verification

[](#searching-for-a-verification)

You can check the status of a verification, or access the results of past verifications using a request ID. The verification object will then provide a rich interface:

```
$client->verify()->search('00e6c3377e5348cdaf567e1417c707a5');

echo "Codes checked for verification: " . $verification->getRequestId() . PHP_EOL;
foreach($verification->getChecks() as $check){
    echo $check->getDate()->format('d-m-y') . ' ' . $check->getStatus() . PHP_EOL;
}
```

#### Payment Verification

[](#payment-verification)

Vonage's [Verify API](https://developer.nexmo.com/verify/overview) has SCA (Secure Customer Authentication) support, required by the PSD2 (Payment Services Directive) and used by applications that need to get confirmation from customers for payments. It includes the payee and the amount in the message.

Start the verification for a payment like this:

```
$request = new \Vonage\Verify\RequestPSD2('14845551212', 'My App');
$response = $client->verify()->requestPSD2($request);
echo "Started verification with an id of: " . $response['request_id'];
```

Once the user inputs the pin code they received, call the `/check` endpoint with the request ID and the pin to confirm the pin is correct.

### Verify Examples (v2)

[](#verify-examples-v2)

#### Starting a Verification

[](#starting-a-verification-1)

Vonage's Verify v2 relies more on asynchronous workflows via. webhooks, and more customisable Verification workflows to the developer. To start a verification, you'll need the API client, which is under the namespace `verify2`.

Making a Verify request needs a 'base' channel of communication to deliver the mode of verification. You can customise these interactions by adding different 'workflows'. For each type of workflow, there is a Verify2 class you can create that will handle the initial workflow for you. For example:

```
$client = new Vonage\Client(
    new Vonage\Client\Credentials\Basic(API_KEY, API_SECRET),
);

$smsRequest = new \Vonage\Verify2\Request\SMSRequest('TO_NUMBER');
$client->verify2()->startVerification($smsRequest);
```

The `SMSRequest` object will resolve defaults for you, and will create a default `workflow` object to use SMS. You can, however, add multiple workflows that operate with fall-back logic. For example, if you wanted to create a Verification that tries to get a PIN code off the user via. SMS, but in case there is a problem with SMS delivery you wish to add a Voice fallback: you can add it.

```
$client = new Vonage\Client(
    new Vonage\Client\Credentials\Basic(API_KEY, API_SECRET),
);

$smsRequest = new \Vonage\Verify2\Request\SMSRequest('TO_NUMBER', 'my-verification');
$voiceWorkflow = new \Vonage\Verify2\VerifyObjects\VerificationWorkflow(\Vonage\Verify2\VerifyObjects\VerificationWorkflow::WORKFLOW_VOICE, 'TO_NUMBER');
$smsRequest->addWorkflow($voiceWorkflow);
$client->verify2()->startVerification($smsRequest);
```

This adds the voice workflow to the original SMS request. The verification request will try and resolve the process in the order that it is given (starting with the default for the type of request).

The base request types are as follows:

- `SMSRequest`
- `WhatsAppRequest`
- `WhatsAppInterativeRequest`
- `EmailRequest`
- `VoiceRequest`
- `SilentAuthRequest`

For adding workflows, you can see the available valid workflows as constants within the `VerificationWorkflow` object. For a better developer experience, you can't create an invalid workflow due to the validation that happens on the object.

#### Check a submitted code

[](#check-a-submitted-code)

To submit a code, you'll need to surround the method in a try/catch due to the nature of the API. If the code is correct, the method will return a `true` boolean. If it fails, it will throw the relevant Exception from the API that will need to be caught.

```
$code = '1234';
try {
    $client->verify2()->check($code);
} catch (\Exception $e) {
    var_dump($e->getMessage())
}
```

#### Webhooks

[](#webhooks)

As events happen during a verification workflow, events and updates will fired as webhooks. Incoming server requests that conform to PSR-7 standards can be hydrated into a webhook value object for nicer interactions. You can also hydrate them from a raw array. If successful, you will receive a value object back for the type of event/update. Possible webhooks are:

- `VerifyEvent`
- `VerifyStatusUpdate`
- `VerifySilentAuthUpdate`

```
// From a request object
$verificationEvent = \Vonage\Verify2\Webhook\Factory::createFromRequest($request);
var_dump($verificationEvent->getStatus());
// From an array
$payload = $request->getBody()->getContents()
$verificationEvent = \Vonage\Verify2\Webhook\Factory::createFromArray($payload);
var_dump($verificationEvent->getStatus());
```

#### Cancelling a request in-flight

[](#cancelling-a-request-in-flight)

You can cancel a request should you need to, before the end user has taken any action.

```
$requestId = 'c11236f4-00bf-4b89-84ba-88b25df97315';
$client->verify2()->cancel($requestId);
```

#### Making a Call

[](#making-a-call)

All `$client->voice()` methods require the client to be constructed with a `Vonage\Client\Credentials\Keypair`, or a `Vonage\Client\Credentials\Container` that includes the `Keypair` credentials:

```
$basic  = new \Vonage\Client\Credentials\Basic(VONAGE_API_KEY, VONAGE_API_SECRET);
$keypair = new \Vonage\Client\Credentials\Keypair(
    file_get_contents(VONAGE_APPLICATION_PRIVATE_KEY_PATH),
    VONAGE_APPLICATION_ID
);

$client = new \Vonage\Client(new \Vonage\Client\Credentials\Container($basic, $keypair));
```

You can start a call using an `OutboundCall` object:

```
$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);
$outboundCall
    ->setAnswerWebhook(
        new \Vonage\Voice\Webhook('https://example.com/webhooks/answer')
    )
    ->setEventWebhook(
        new \Vonage\Voice\Webhook('https://example.com/webhooks/event')
    )
;

$response = $client->voice()->createOutboundCall($outboundCall);
```

If you would like to have the system randomly pick a FROM number from the numbers linked to an application, you can leave off the second parameter to `\Vonage\Voice\OutboundCall`'s constructor, and the system will select a number at random for you.

### Using the SimSwap API

[](#using-the-simswap-api)

SimSwap uses CAMARA standards in order to determine how long a SIM has been inside a cellular device. This means the auth mechanism is slightly more complex than other APIs. You will need:

> To have your own *Subscriber Number* that has been registered with the Vonage Global Network Platform. Your Dashboard Application ID Your Private Key

#### Usage

[](#usage-1)

There are two available methods for this API: `checkSimSwap` and `checkSimSwapDate`.

Here is an example of using both:

```
$credentials = new \Vonage\Client\Credentials\Gnp(
    '0777888888',
    file_get_contents('./private.key'),
    '0dadaeb4-7c79-4d39-b4b0-5a6cc08bf537'
);

$client = new \Vonage\Client($credentials);

$swapResult = $client->simswap()->checkSimSwap('07999999999', 500);

if ($swapResult) {
    echo "Warning: SIM Swapped recently"
} else {
    echo "SIM OK"
};

// Finding the swap date
echo $client->simswap()->checkSimSwapDate('07999999999');
```

### Using the Number Verification API

[](#using-the-number-verification-api)

Number Verification uses CAMARA API standards and is used to determine whether a request is valid. Unlike other SDKs, the SDK is split between the start of the process and the end of the process.

You will need:

> To have your own *Subscriber Number* that has been registered with the Vonage Global Network Platform. Your Dashboard Application ID Your Private Key, downloaded from the Vonage Dashboard

#### Usage

[](#usage-2)

1. Your backend needs to serve a custom URL that will be used to fire off the verification request. To do this, use the `buildFrontEndUrl()` method on the client. When calling this, you'll need to supply the route your application is expected to receive a callback from containing a unique `code`. You will need to have an authorised phone number in an authorised territory for this to work. Here is dummy example:

```
class VerificationController extends MyFrameworkAbsractController
{
    $credentials = new \Vonage\Client\Credentials\Gnp(
        '077380777111',
        file_get_contents('../private.key'),
        '0dadaeb4-7c79-4d39-b4b0-5a6cc08bf537'
    )

    $client = new \Vonage\Client($credentials);

    $verifyUrl = $client->numberVerification()->buildFrontEndUrl(
        '07777777777',
        'https://myapp.com/auth/numberVerify'
    );

    return $this->render('verify.html.twig', [
        'verifyLink' => $verifyUrl
    ]);
}
```

2. Your backend then needs to be able to configured to consume the incoming webhook. The SDK will take care care of handling the Auth methods required to do this, once you have extracted the `code`. The method returns a boolean from the API. Here is an example:

```
$code = $request->get('code');

$result = $client->numberVerification()->verifyNumber(
    '09947777777',
    $code
);

if ($result) {
    Auth::login($request->user())
}

return redirect('login');
}
```

### Using the Conversations API

[](#using-the-conversations-api)

This API is used for in-app messaging and is contains a wide range of features and concepts. For more information, take a look at the [API Documentation](https://developer.vonage.com/en/api/conversation?source=conversation)

#### Retrieve a list of Conversations with Filter

[](#retrieve-a-list-of-conversations-with-filter)

```
$credentials = new \Vonage\Client\Credentials\Keypair(file_get_contents('./path-to-my-key.key', 'my-app-id'));
$client = new \Vonage\Client($credentials);
$filter = new \Vonage\Conversation\Filter\ListConversationFilter();
$filter->setStartDate('2018-01-01 10:00:00');
$filter->setEndDate('2019-01-01 10:00:00')

$conversations = $client->conversations()->listConversations($filter)

var_dump($conversations);
```

#### Create a Conversation

[](#create-a-conversation)

```
$credentials = new \Vonage\Client\Credentials\Keypair(file_get_contents('./path-to-my-key.key', 'my-app-id'));
$client = new \Vonage\Client($credentials);

$conversation = new CreateConversationRequest('customer_chat', 'Customer Chat', 'https://example.com/image.png');
$conversation->setTtl(60);

$conversationNumber = new ConversationNumber('447700900000');

$conversationCallback = new ConversationCallback('https://example.com/eventcallback');
$conversationCallback->setEventMask('member:invited, member:joined');
$conversationCallback->setApplicationId('afa393df-2c46-475b-b2d6-92da4ea05481');
$conversationCallback->setNccoUrl('https://example.com/ncco');

$conversation->setNumber($conversationNumber);
$conversation->setConversationCallback($conversationCallback);

$response = $this->conversationsClient->createConversation($conversation);

var_dump($response);
```

#### List Members in a Conversation

[](#list-members-in-a-conversation)

```
$credentials = new \Vonage\Client\Credentials\Keypair(file_get_contents('./path-to-my-key.key', 'my-app-id'));
$client = new \Vonage\Client($credentials);

$filter = new ListUserConversationsFilter();
$filter->setState('INVITED');
$filter->setIncludeCustomData(true);
$filter->setOrderBy('created');
$filter->setStartDate('2018-01-01 10:00:00');
$filter->setEndDate('2018-01-01 12:00:00');
$filter->setPageSize(5);
$filter->setOrder('asc');

$response = $this->conversationsClient->listUserConversationsByUserId('CON-d66d47de-5bcb-4300-94f0-0c9d4b948e9a');

foreach ($response as $member) {
    $members[] = $member;
}

var_dump($members);
```

#### Create a Member in a Conversation

[](#create-a-member-in-a-conversation)

```
$channel = Channel::createChannel(Channel::CHANNEL_TYPE_APP);
$channel->addUserFromTypes([
    'sms',
    'phone'
]);

$channel->addUserToField('USR-82e028d9-9999-4f1e-8188-604b2d3471ec');

$createMemberRequest = new CreateMemberRequest(
    'invited',
    $channel,
    'USR-82e028d9-5201-4f1e-8188-604b2d3471ec',
    'my_user_name',
);

$createMemberRequest->setAudioPossible(true);
$createMemberRequest->setAudioEnabled(true);
$createMemberRequest->setAudioEarmuffed(false);
$createMemberRequest->setAudioMuted(false);
$createMemberRequest->setKnockingId('4f1e-8188');
$createMemberRequest->setMemberIdInviting('MEM-63f61863-4a51-4f6b-86e1-46edebio0391');
$createMemberRequest->setFrom('value');

$response = $this->conversationsClient->createMember(
    $createMemberRequest,
    'CON-63f61863-4a51-4f6b-86e1-46edebio0391'
);

var_dump($response);
```

### Building a call with NCCO Actions

[](#building-a-call-with-ncco-actions)

### Create an Event

[](#create-an-event)

Full parameter lists for NCCO Actions can be found in the [Voice API Docs](https://developer.nexmo.com/voice/voice-api/ncco-reference).

Each of these examples uses the following structure to add actions to a call:

```
$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);
$ncco = new NCCO();

// ADD ACTIONS TO THE NCCO OBJECT HERE

$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);
```

### Record a call

[](#record-a-call)

```
$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);

$ncco = new NCCO();
$ncco->addAction(\Vonage\Voice\NCCO\Action\Record::factory([
    'eventUrl' => 'https://example.com/webhooks/event'
]);
$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);
```

Your webhook url will receive a payload like this:

```
{
  "start_time": "2020-10-29T14:30:24Z",
  "recording_url": "https://api.nexmo.com/v1/files/",
  "size": 27918,
  "recording_uuid": "",
  "end_time": "2020-10-29T14:30:31Z",
  "conversation_uuid": "",
  "timestamp": "2020-10-29T14:30:31.619Z"
}

```

You can then fetch and store the recording like this:

```
$recordingId = '';
$recordingUrl = 'https://api.nexmo.com/v1/files/' . $recordingId;
$data = $client->get($recordingUrl);
file_put_contents($recordingId.'.mp3', $data->getBody());

```

### Send a text to voice call

[](#send-a-text-to-voice-call)

```
$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);

$ncco = new NCCO();
$ncco->addAction(new \Vonage\Voice\NCCO\Action\Talk('This is a text to speech call from Vonage'));
$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);
```

### Stream an audio file on a call

[](#stream-an-audio-file-on-a-call)

```
$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);

$ncco = new NCCO();
$ncco->addAction(new \Vonage\Voice\NCCO\Action\Stream('https://example.com/sounds/my-audio.mp3'));
$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);
```

### Collect user input from a call

[](#collect-user-input-from-a-call)

Supports keypad entry as well as voice. NB. the input action must follow an action with `bargeIn` set to `true`

```
$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);

$ncco = new NCCO();

$ncco->addAction(\Vonage\Voice\NCCO\Action\Talk::factory('Please record your name.',[
  'bargeIn' => true,
]));

$ncco->addAction(\Vonage\Voice\NCCO\Action\Input::factory([
  'eventUrl' => 'https://example.com/webhooks/event',
  'type' => [
    'speech',
  ],
  'speech' => [
    'endOnSilence' => true,
  ],
]));

$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);
```

The webhook URL will receive a payload containing the input from the user with relative confidence ratings for speech input.

### Send a notification to a webhook url

[](#send-a-notification-to-a-webhook-url)

```
$outboundCall = new \Vonage\Voice\OutboundCall(
    new \Vonage\Voice\Endpoint\Phone('14843331234'),
    new \Vonage\Voice\Endpoint\Phone('14843335555')
);

$ncco = new NCCO();
$ncco->addAction(new \Vonage\Voice\NCCO\Action\Talk('We are just testing the notify function, you do not need to do anything.'));
$ncco->addAction(new \Vonage\Voice\NCCO\Action\Notify([
  'foo' => 'bar',
], new Vonage\Voice\Webhook('https://example.com/webhooks/notify')));
$outboundCall->setNCCO($ncco);

$response = $client->voice()->createOutboundCall($outboundCall);
```

The webhook URL will receive a payload as specified in the request.

### Fetching a Call

[](#fetching-a-call)

You can fetch a call using a `Vonage\Call\Call` object, or the call's UUID as a string:

```
$call = $client->voice()->get('3fd4d839-493e-4485-b2a5-ace527aacff3');

echo $call->getDirection();
```

You can also search for calls using a Filter.

```
$filter = new \Vonage\Voice\Filter\VoiceFilter();
$filter->setStatus('completed');
foreach($client->search($filter) as $call){
    echo $call->getDirection();
}
```

### Creating an Application

[](#creating-an-application)

Application are configuration containers. You can create one using an array structure:

```
$application = new \Vonage\Application\Application();
$application->fromArray([
 'name' => 'test application',
 'keys' => [
     'public_key' => '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCA\nKOxjsU4pf/sMFi9N0jqcSLcjxu33G\nd/vynKnlw9SENi+UZR44GdjGdmfm1\ntL1eA7IBh2HNnkYXnAwYzKJoa4eO3\n0kYWekeIZawIwe/g9faFgkev+1xsO\nOUNhPx2LhuLmgwWSRS4L5W851Xe3f\nUQIDAQAB\n-----END PUBLIC KEY-----\n'
 ],
 'capabilities' => [
     'voice' => [
         'webhooks' => [
             'answer_url' => [
                 'address' => 'https://example.com/webhooks/answer',
                 'http_method' => 'GET',
             ],
             'event_url' => [
                 'address' => 'https://example.com/webhooks/event',
                 'http_method' => 'POST',
             ],
         ]
     ],
     'messages' => [
         'webhooks' => [
             'inbound_url' => [
                 'address' => 'https://example.com/webhooks/inbound',
                 'http_method' => 'POST'

             ],
             'status_url' => [
                 'address' => 'https://example.com/webhooks/status',
                 'http_method' => 'POST'
             ]
         ]
     ],
     'rtc' => [
         'webhooks' => [
             'event_url' => [
                 'address' => 'https://example.com/webhooks/event',
                 'http_method' => 'POST',
             ],
         ]
     ],
     'vbc' => []
 ]
]);

$client->applications()->create($application);
```

You can also pass the client an application object:

```
$a = new Vonage\Application\Application();

$a->setName('PHP Client Example');
$a->getVoiceConfig()->setWebhook('answer_url', 'https://example.com/webhooks/answer', 'GET');
$a->getVoiceConfig()->setWebhook('event_url', 'https://example.com/webhooks/event', 'POST');
$a->getMessagesConfig()->setWebhook('status_url', 'https://example.com/webhooks/status', 'POST');
$a->getMessagesConfig()->setWebhook('inbound_url', 'https://example.com/webhooks/inbound', 'POST');
$a->getRtcConfig()->setWebhook('event_url', 'https://example.com/webhooks/event', 'POST');
$a->disableVbc();

$client->applications()->create($a);
```

### Fetching Applications

[](#fetching-applications)

You can iterate over all your applications:

```
foreach($client->applications()->getAll() as $application){
    echo $application->getName() . PHP_EOL;
}
```

Or you can fetch an application using a string UUID, or an application object.

```
$application = $client->applications()->get('1a20a124-1775-412b-b623-e6985f4aace0');
```

### Updating an Application

[](#updating-an-application)

Once you have an application object, you can modify and save it.

```
$application = $client->applications()->get('1a20a124-1775-412b-b623-e6985f4aace0');

$application->setName('Updated Application');
$client->applications()->update($application);
```

### List Your Numbers

[](#list-your-numbers)

You can list the numbers owned by your account and optionally include filtering:

`search_pattern`:

- `0` - the number begins with `pattern`
- `1` - the number includes `pattern`
- `2` - the number ends with `pattern`

```
$filter = new \Vonage\Numbers\Filter\OwnedNumbers();
$filter
    ->setPattern(234)
    ->setSearchPattern(\Vonage\Numbers\Filter\OwnedNumbers::SEARCH_PATTERN_CONTAINS)
;
$response = $client->numbers()->searchOwned(null, $filter);
```

`has_application`:

- `true` - The number is attached to an application
- `false` - The number is not attached to an application

```
$filter = new \Vonage\Numbers\Filter\OwnedNumbers();
$filter->setHasApplication(true);
$response = $client->numbers()->searchOwned($filter);
```

`application_id`:

- Supply an application ID to get all the numbers associated with the requesting application

```
$filter = new \Vonage\Numbers\Filter\OwnedNumbers();
$filter->setApplicationId("66c04cea-68b2-45e4-9061-3fd847d627b8");
$response = $client->numbers()->searchOwned($filter);
```

### Search Available Numbers

[](#search-available-numbers)

You can search for numbers available to purchase in a specific country:

```
$numbers = $client->numbers()->searchAvailable('US');
```

By default, this will only return the first 10 results. You can add an additional `\Vonage\Numbers\Filter\AvailableNumbers`filter to narrow down your search.

### Purchase a Number

[](#purchase-a-number)

To purchase a number, you can pass in a value returned from number search:

```
$numbers = $client->numbers()->searchAvailable('US');
$number = $numbers->current();
$client->numbers()->purchase($number->getMsisdn(), $number->getCountry());
```

Or you can specify the number and country manually:

```
$client->numbers()->purchase('14155550100', 'US');
```

### Update a Number

[](#update-a-number)

To update a number, use `numbers()->update` and pass in the configuration options you want to change. To clear a setting, pass in an empty value.

```
$number = $client->numbers()->get(VONAGE_NUMBER);
$number
    ->setAppId('1a20a124-1775-412b-b623-e6985f4aace0')
    ->setVoiceDestination('447700900002', 'tel')
    ->setWebhook(
        \Vonage\Number\Number::WEBHOOK_VOICE_STATUS,
        'https://example.com/webhooks/status'
    )
    ->setWebhook(
        \Vonage\Number\Number::WEBHOOK_MESSAGE,
        'https://example.com/webhooks/inbound-sms'
    )
;
$client->numbers()->update($number);
echo "Number updated" . PHP_EOL;
```

### Cancel a Number

[](#cancel-a-number)

To cancel a number, provide the `msisdn`:

```
$client->numbers()->cancel('447700900002');
```

### Managing Secrets

[](#managing-secrets)

An API is provided to allow you to rotate your API secrets. You can create a new secret (up to a maximum of two secrets) and delete the existing one once all applications have been updated.

To get a list of the secrets:

```
$secretsCollection = $client->account()->listSecrets(API_KEY);
/** @var \Vonage\Account\Secret $secret */
foreach($secretsCollection->getSecrets() as $secret) {
    echo "ID: " . $secret->getId() . " (created " . $secret->getCreatedAt() .")\n";
}
```

You can create a new secret (the created dates will help you know which is which):

```
$client->account()->createSecret(API_KEY, 'awes0meNewSekret!!;');
```

And delete the old secret (any application still using these credentials will stop working):

```
try {
    $response = $client->account()->deleteSecret(API_KEY, 'd0f40c7e-91f2-4fe0-8bc6-8942587b622c');
} catch(\Vonage\Client\Exception\RequestException $e) {
    echo $e->getMessage();
}
```

### Pricing

[](#pricing)

#### Prefix Pricing

[](#prefix-pricing)

If you know the prefix of a country you want to call, you can use the `prefix-pricing` endpoint to find out costs to call that number. Each prefix can return multiple countries (e.g. `1` returns `US`, `CA` and `UM`):

```
$results = $client->account()->getPrefixPricing('1');
foreach ($results as $price) {
    echo $price->getCountryCode().PHP_EOL;
    echo $price->getCountryName().PHP_EOL;
    foreach ($price->getNetworks() as $network) {
        echo $network->getName() .' :: '.$network->getCode().' :: '.$network->getPrefixPrice().PHP_EOL;
    }
    echo "----------------".PHP_EOL;
}
```

### Check your Balance

[](#check-your-balance)

Check how much credit remains on your account:

```
$response = $client->account()->getBalance();
echo round($response->getBalance(), 2) . " EUR\n";
```

### View and Change Account Configuration

[](#view-and-change-account-configuration)

Inspect the current settings on the account:

```
$response = $client->account()->getConfig();
print_r($response->toArray());
```

Update the default callback URLs for incoming SMS messages and delivery receipts:

```
$response = $client->account()->updateConfig([
    "sms_callback_url" => "http://example.com/webhooks/incoming-sms",
    "dr_callback_url" => "http://example.com/webhooks/delivery-receipt"
]);
print_r($response->toArray());
```

### Use SimSwap to Check the Status and Date of a SIM in a handset

[](#use-simswap-to-check-the-status-and-date-of-a-sim-in-a-handset)

In order to use Vonage's Network APIs you'll need to be enabled within the [Vonage Network Registry](https://developer.vonage.com/en/getting-started-network/registration?source=sim-swap)

Once you have a registered MSNDIN, you will be able to use SimSwap.

SimSwap uses the Global Network Platform authentication mechanism, so the authorisation flow looks a little different from other API Clients. Under the hood, the SDK will handle multiple calls for you to configure a CAMARA standard access token.

Here's an example of checking if a SIM has been recently been swapped:

```
$credentials = new \Vonage\Client\Credentials\Gnp(
    'tel:+447700900000',
    fopen('./my-private-key'),
    'my-application-id'
);

$client = new \Vonage\Client($credentials);

if ($client->simswap()->checkSimSwap('07700009999', 240)) {
    echo 'Warning: SIM Swap Check Failed'
} else {
    echo 'SIM Swap Check Pass'
}
```

And here is how you retrieve the swap date:

```
$credentials = new \Vonage\Client\Credentials\Gnp(
    'tel:+447700900000',
    fopen('./my-private-key'),
    'my-application-id'
);

$client = new \Vonage\Client($credentials);
$date = $client->simswap()->checkSimSwapDate('07700009999')

echo $date;
```

### Get Information About a Number

[](#get-information-about-a-number)

The [Number Insights API](https://developer.nexmo.com/api/number-insight) allows a user to check that a number is valid and to find out more about how to use it.

#### Basic and Standard Usage

[](#basic-and-standard-usage)

You can use either the `basic()` or `standard()` methods (an `advanced()` method is available, but it is recommended to use the async option to get advanced info), like this:

```
try {
  $insights = $client->insights()->basic(PHONE_NUMBER);

  echo $insights->getNationalFormatNumber();
} catch (Exception $e) {
  // for the Vonage-specific exceptions, try the `getEntity()` method for more diagnostic information
}
```

The data is returned in the `$insights` variable in the example above.

#### Advanced Usage

[](#advanced-usage)

To get advanced insights, use the async feature and supply a URL for the webhook to be sent to:

```
try {
  $client->insights()->advancedAsync(PHONE_NUMBER, 'http://example.com/webhooks/number-insights');
} catch (Exception $e) {
  // for the Vonage-specific exceptions, try the `getEntity()` method for more diagnostic information
}
```

Check out the [documentation](https://developer.nexmo.com/number-insight/code-snippets/number-insight-advanced-async-callback) for what to expect in the incoming webhook containing the data you requested.

### Subaccount Examples

[](#subaccount-examples)

This API is used to create and configure subaccounts related to your primary account and transfer credit, balances and bought numbers between accounts. The subaccounts API is disabled by default. If you want to use subaccounts, [contact support](https://api.support.vonage.com) to have the API enabled on your account.

#### Get a list of Subaccounts

[](#get-a-list-of-subaccounts)

```
$client = new \Vonage\Client(new \Vonage\Client\Credentials\Basic(API_KEY, API_SECRET));
$apiKey = '34kokdf';
$subaccounts = $client->subaccount()->getSubaccounts($apiKey);
var_dump($subaccounts);
```

#### Create a Subaccount

[](#create-a-subaccount)

```
$client = new \Vonage\Client(new \Vonage\Client\Credentials\Basic(API_KEY, API_SECRET));

$apiKey = 'acc6111f';

$payload = [
    'name' => 'sub name',
    'secret' => 's5r3fds',
    'use_primary_account_balance' => false
];

$account = new Account();
$account->fromArray($payload);

$response = $client->subaccount()->createSubaccount($apiKey, $account);
var_dump($response);
```

#### Get a Subaccount

[](#get-a-subaccount)

```
$client = new \Vonage\Client(new \Vonage\Client\Credentials\Basic(API_KEY, API_SECRET));

$apiKey = 'acc6111f';
$subaccountKey = 'bbe6222f';

$response = $client->subaccount()->getSubaccount($apiKey, $subaccountKey);
var_dump($response);
```

#### Update a Subaccount

[](#update-a-subaccount)

```
$client = new \Vonage\Client(new \Vonage\Client\Credentials\Basic(API_KEY, API_SECRET));

$apiKey = 'acc6111f';
$subaccountKey = 'bbe6222f';

$payload = [
    'suspended' => true,
    'use_primary_account_balance' => false,
    'name' => 'Subaccount department B'
];

$account = new Account();
$account->fromArray($payload);

$response = $client->subaccount()->updateSubaccount($apiKey, $subaccountKey, $account)
var_dump($response);
```

#### Get a list of Credit Transfers

[](#get-a-list-of-credit-transfers)

```
$client = new \Vonage\Client(new \Vonage\Client\Credentials\Basic(API_KEY, API_SECRET));

$apiKey = 'acc6111f';
$filter = new Vonage\Subaccount\Filter\Subaccount(['subaccount' => '35wsf5'])
$transfers = $client->subaccount()->getCreditTransfers($apiKey);
var_dump($transfers);
```

#### Transfer Credit between accounts

[](#transfer-credit-between-accounts)

```
$client = new \Vonage\Client(new \Vonage\Client\Credentials\Basic(API_KEY, API_SECRET));

$apiKey = 'acc6111f';

$transferRequest = (new TransferCreditRequest($apiKey))
    ->setFrom('acc6111f')
    ->setTo('s5r3fds')
    ->setAmount('123.45')
    ->setReference('this is a credit transfer');

$response = $this->subaccountClient->makeCreditTransfer($transferRequest);
```

#### Get a list of Balance Transfers

[](#get-a-list-of-balance-transfers)

```
$client = new \Vonage\Client(new \Vonage\Client\Credentials\Basic(API_KEY, API_SECRET));
$apiKey = 'acc6111f';

$filter = new \Vonage\Subaccount\Filter\Subaccount(['end_date' => '2022-10-02']);
$transfers = $client->subaccount()->getBalanceTransfers($apiKey, $filter);
```

#### Transfer Balance between accounts

[](#transfer-balance-between-accounts)

```
$client = new \Vonage\Client(new \Vonage\Client\Credentials\Basic(API_KEY, API_SECRET));

$apiKey = 'acc6111f';

$transferRequest = (new TransferBalanceRequest($apiKey))
    ->setFrom('acc6111f')
    ->setTo('s5r3fds')
    ->setAmount('123.45')
    ->setReference('this is a credit transfer');

$response = $client->subaccount()->makeBalanceTransfer($transferRequest);
var_dump($response);
```

#### Transfer a Phone Number between accounts

[](#transfer-a-phone-number-between-accounts)

```
$client = new \Vonage\Client(new \Vonage\Client\Credentials\Basic(API_KEY, API_SECRET));
$apiKey = 'acc6111f';

$numberTransferRequest = (new NumberTransferRequest($apiKey))
    ->setFrom('acc6111f')
    ->setTo('s5r3fds')
    ->setNumber('4477705478484')
    ->setCountry('GB');

$response = $client->subaccount()->makeNumberTransfer($numberTransferRequest);
var_dump($response);
```

Supported APIs
--------------

[](#supported-apis)

APIAPI Release StatusSupported?Account APIGeneral Availability✅Alerts APIGeneral Availability✅Application APIGeneral Availability✅Audit APIBeta❌Conversation APIBeta❌Dispatch APIBeta❌External Accounts APIBeta❌Media APIBeta❌Meetings APIGeneral Availability✅Messages APIGeneral Availability✅Number Insight APIGeneral Availability✅Number Management APIGeneral Availability✅Pricing APIGeneral Availability✅ProActive Connect APIBeta❌Redact APIGeneral Availability✅Reports APIBeta❌SMS APIGeneral Availability✅Subaccounts APIGeneral Availability✅Verify APIGeneral Availability✅Verify API (Version 2)General Availability✅Voice APIGeneral Availability✅Troubleshooting
---------------

[](#troubleshooting)

### Checking for Deprecated Features

[](#checking-for-deprecated-features)

Over time, the Vonage APIs evolve and add new features, change how existing features work, and deprecate and remove older methods and features. To help developers know when deprecation changes are being made, the SDK will trigger an `E_USER_DEPRECATION` warning. These warnings will not stop the execution of code, but can be an annoyance in production environments.

To help with this, by default these notices are suppressed. In development, you can enable these warnings by passing an additional configuration option to the `\Vonage\Client` constructor, called `show_deprecations`. Enabling this option will show all deprecation notices.

```
$client = new Vonage\Client(
    new Vonage\Client\Credentials\Basic(API_KEY, API_SECRET),
    [
        'show_deprecations' => true
    ]
);
```

If you notice an excessive amount of deprecation notices in production environments, make sure the configuration option is absent, or at least set to `false`.

### `unable to get local issuer certificate`

[](#unable-to-get-local-issuer-certificate)

Some users have issues making requests due to the following error:

```
Fatal error: Uncaught exception 'GuzzleHttp\Exception\RequestException' with message 'cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)'

```

This is due to some PHP installations not shipping with a list of trusted CA certificates. This is a system configuration problem, and not specific to either cURL or Vonage.

> *IMPORTANT*: In the next paragraph we provide a link to a CA certificate bundle. Vonage do not guarantee the safety of this bundle, and you should review it yourself before installing any CA bundle on your machine.

To resolve this issue, download a list of trusted CA certificates (e.g. the [curl](https://curl.haxx.se/ca/cacert.pem) bundle) and copy it on to your machine. Once this is done, edit `php.ini` and set the `curl.cainfo` parameter:

```
# Linux/MacOS
curl.cainfo = "/etc/pki/tls/cacert.pem"
# Windows
curl.cainfo = "C:\php\extras\ssl\cacert.pem"

```

### Pass custom HTTP client

[](#pass-custom-http-client)

We allow use of any HTTPlug adapter or PSR-18 compatible HTTP client, so you can create a client with alternative configuration if you need it, for example to take account of a local proxy, or deal with something else specific to your setup.

Here's an example that reduces the default timeout to 5 seconds to avoid long delays if you have no route to our servers:

```
$adapter_client = new Http\Adapter\Guzzle6\Client(new GuzzleHttp\Client(['timeout' => 5]));
$vonage_client = new Vonage\Client(new Vonage\Client\Credentials\Basic($api_key, $api_secret), [], $adapter_client);
```

### Accessing Response Data

[](#accessing-response-data)

When things go wrong, you'll receive an `Exception`. The Vonage exception classes `Vonage\Client\Exception\RequestException` and `Vonage\Client\Exception\ServerException` support an additional `getEntity()` method which you can use in addition to `getCode()` and `getMessage()` to find out more about what went wrong. The entity returned will typically be an object related to the operation, or the response object from the API call.

### Composer installation fails due to Guzzle Adapter

[](#composer-installation-fails-due-to-guzzle-adapter)

If you have a conflicting package installation that cannot co-exist with our recommended `guzzlehttp/guzzle` package, then you may install the package `vonage/client-core` along with any package satisfying the `php-http/client-implementation` requirement.

See the [Packagist page for client-implementation](https://packagist.org/providers/php-http/client-implementation) for options.

### Enabling Request/Response Logging

[](#enabling-requestresponse-logging)

Our client library has support for logging the request and response for debugging via PSR-3 compatible logging mechanisms. If the `debug` option is passed into the client and a PSR-3 compatible logger is set in our client's service factory, we will use the logger for debugging purposes.

```
$client = new \Vonage\Client(new \Vonage\Client\Credentials\Basic('abcd1234', 's3cr3tk3y'), ['debug' => true]);
$logger = new \Monolog\Logger('test');
$logger->pushHandler(new \Monolog\Handler\StreamHandler(__DIR__ . '/log.txt', \Monolog\Logger::DEBUG));
$client->getFactory()->set(\PSR\Log\LoggerInterface::class, $logger);
```

**ENABLING DEBUGGING LOGGING HAS THE POTENTIAL FOR LOGGING SENSITIVE INFORMATION, DO NOT ENABLE IN PRODUCTION**

Test Suite
----------

[](#test-suite)

This library has a full test suite designed to be run with [PHPUnit](https://phpunit.de).

To run, use composer:

```
composer test

```

> Please note: this test suite is large, and may require a considerable amount of memory to run. If you encounter the "too many files open" error in MacOS or Linux, there is a hack to increase the amount of file pointers permitted. Increase the amount of files that can be open by entering the following on the command line (10240 is the maximum amount of pointers MacOS will open currently):

```
 ulimit -n 10240

```

Contributing
------------

[](#contributing)

This library is actively developed, and we love to hear from you! Please feel free to [create an issue](https://github.com/Vonage/vonage-php-core/issues) or [open a pull request](https://github.com/Vonage/vonage-php-core/pulls) with your questions, comments, suggestions and feedback.

###  Health Score

79

—

ExcellentBetter than 100% of packages

Maintenance84

Actively maintained with recent releases

Popularity71

Solid adoption and visibility

Community46

Growing community involvement

Maturity99

Battle-tested with a long release history

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~26 days

Recently: every ~90 days

Total

135

Last Release

132d ago

Major Versions

0.4.0 → 1.0.02017-08-29

1.8.1 → 2.0.02019-09-19

2.10.0 → 3.0.02022-01-25

2.10.1 → 3.0.22022-02-11

3.1.6 → 4.0.02023-01-11

PHP version history (9 changes)1.0.0-alpha1PHP &gt;=5.4

1.0.0PHP &gt;=5.6

2.0.0PHP &gt;=7.1

2.4.0PHP &gt;=7.2

3.0.0PHP ~7.4 || ~8.0 || ~8.1

4.0.0PHP ~8.0 || ~8.1 || ~8.2

4.6.0PHP ~8.1 || ~8.2 || ~8.3

4.11.0PHP ~8.1 || ~8.2 || ~8.3 || ~8.4

4.12.0PHP ~8.1 || ~8.2 || ~8.3 || ~8.4 || ~8.5

### Community

Maintainers

![](https://www.gravatar.com/avatar/8c2583b67d4e1a4ade23b6ce271980d18bf3facb4ea3f0610fded770f380d17d?d=identicon)[dragonmantank](/maintainers/dragonmantank)

![](https://avatars.githubusercontent.com/u/2683897?v=4)[Vonage](/maintainers/Vonage)[@Vonage](https://github.com/Vonage)

![](https://www.gravatar.com/avatar/efc1f4119b02a988612122f19b2e021c8e919e5018f645d453a62b47064790b2?d=identicon)[SecondeJK](/maintainers/SecondeJK)

---

Top Contributors

[![dragonmantank](https://avatars.githubusercontent.com/u/108948?v=4)](https://github.com/dragonmantank "dragonmantank (168 commits)")[![SecondeJK](https://avatars.githubusercontent.com/u/17067659?v=4)](https://github.com/SecondeJK "SecondeJK (156 commits)")[![tjlytle](https://avatars.githubusercontent.com/u/125074?v=4)](https://github.com/tjlytle "tjlytle (81 commits)")[![mheap](https://avatars.githubusercontent.com/u/59130?v=4)](https://github.com/mheap "mheap (79 commits)")[![lornajane](https://avatars.githubusercontent.com/u/172607?v=4)](https://github.com/lornajane "lornajane (45 commits)")[![manchuck](https://avatars.githubusercontent.com/u/192776?v=4)](https://github.com/manchuck "manchuck (18 commits)")[![Pier-d](https://avatars.githubusercontent.com/u/61907396?v=4)](https://github.com/Pier-d "Pier-d (7 commits)")[![ankurk91](https://avatars.githubusercontent.com/u/6111524?v=4)](https://github.com/ankurk91 "ankurk91 (4 commits)")[![erickskrauch](https://avatars.githubusercontent.com/u/4787256?v=4)](https://github.com/erickskrauch "erickskrauch (3 commits)")[![ash-jc-allen](https://avatars.githubusercontent.com/u/39652331?v=4)](https://github.com/ash-jc-allen "ash-jc-allen (3 commits)")[![driesvints](https://avatars.githubusercontent.com/u/594614?v=4)](https://github.com/driesvints "driesvints (3 commits)")[![arubacao](https://avatars.githubusercontent.com/u/7462542?v=4)](https://github.com/arubacao "arubacao (3 commits)")[![SoftCreatR](https://avatars.githubusercontent.com/u/81188?v=4)](https://github.com/SoftCreatR "SoftCreatR (3 commits)")[![yosatak](https://avatars.githubusercontent.com/u/6265686?v=4)](https://github.com/yosatak "yosatak (2 commits)")[![derickr](https://avatars.githubusercontent.com/u/208074?v=4)](https://github.com/derickr "derickr (2 commits)")[![footballencarta](https://avatars.githubusercontent.com/u/1312258?v=4)](https://github.com/footballencarta "footballencarta (2 commits)")[![SergkeiM](https://avatars.githubusercontent.com/u/3294939?v=4)](https://github.com/SergkeiM "SergkeiM (2 commits)")[![vinkla](https://avatars.githubusercontent.com/u/499192?v=4)](https://github.com/vinkla "vinkla (2 commits)")[![samyrataylor](https://avatars.githubusercontent.com/u/15961687?v=4)](https://github.com/samyrataylor "samyrataylor (1 commits)")[![Starfox64](https://avatars.githubusercontent.com/u/1530720?v=4)](https://github.com/Starfox64 "Starfox64 (1 commits)")

---

Tags

developer-destinationmessagingnexmophonephpserver-sdksmstext-messagetext-to-speechtwo-factor-authenticationvoicevonage

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/vonage-client-core/health.svg)

```
[![Health](https://phpackages.com/badges/vonage-client-core/health.svg)](https://phpackages.com/packages/vonage-client-core)
```

###  Alternatives

[cakephp/cakephp

The CakePHP framework

8.8k18.5M1.6k](/packages/cakephp-cakephp)[deeplcom/deepl-php

Official DeepL API Client Library

2616.2M66](/packages/deeplcom-deepl-php)[contao/core-bundle

Contao Open Source CMS

1231.6M2.4k](/packages/contao-core-bundle)[simplesamlphp/simplesamlphp-module-oidc

A SimpleSAMLphp module adding support for the OpenID Connect protocol

5016.9k1](/packages/simplesamlphp-simplesamlphp-module-oidc)[oxid-esales/graphql-base

OXID eSales GraphQL base module

24101.0k10](/packages/oxid-esales-graphql-base)[rareloop/lumberjack-core

A powerful MVC framework for the modern WordPress developer. Write better, more expressive and easier to maintain code

42155.0k19](/packages/rareloop-lumberjack-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
