Skip to content

voicetel/php-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“ž VoiceTel PHP SDK

The official PHP client for the VoiceTel REST API β€” provision numbers, place orders, validate e911, send messages, and manage your account, with modern PHP 8.1+ ergonomics and battle-tested Guzzle transport.

Version PHP License Coverage

πŸ“š Table of Contents

✨ Features

πŸ›‘οΈ Modern PHP, Strictly Typed

  • PHP 8.1+ end-to-end β€” readonly properties, native enums, named arguments, typed everywhere.
  • ErrorKind enum for HTTP error classification: BadRequest, Authentication, PermissionDenied, NotFound, Conflict, RateLimit, Server, Unknown.
  • PSR-4 autoloading under VoiceTel\Sdk\, plays nicely with Symfony, Laravel, and every other Composer-aware framework.
  • PHPStan level 8 clean across the entire src/ tree.

πŸ” Production-Grade Transport

  • Built on Guzzle 7 β€” the de-facto HTTP client in the PHP ecosystem.
  • Automatic retry with exponential backoff on 429 / 5xx β€” honors Retry-After headers, capped at 8s.
  • Configurable timeout per client (defaults to 30s).
  • Bearer auth managed for you; the password β†’ key exchange is one method call ($client->login(...)).
  • Structured ApiError with typed kind so you can match ($e->kind) { ErrorKind::RateLimit => ... } without parsing HTTP status codes.
  • Envelope-aware β€” strips the {"status":"success","data": ...} wrapper before returning the inner payload.

πŸ“ž Complete API Coverage (73 operations)

  • Numbers β€” list, get, add, remove, route, translate, CNAM, LIDB, fax, forward, SMS, messaging campaigns, port-out PIN, account moves.
  • Account β€” profile, sub-accounts, CDRs, credits, payments, MRC, registration, password recovery.
  • e911 β€” record provisioning, address validation, lookup, removal.
  • Gateways β€” list, create, update, delete, view bound numbers.
  • Messaging β€” SMS & MMS sending, message history, 10DLC brand and campaign registration, per-number messaging state.
  • Lookups β€” CNAM and LRN dips.
  • iNumbering β€” inventory search, coverage queries, number orders, port-in submissions, port-out availability checks.
  • Support β€” ticket create / read / update / delete, threaded messages, replies.
  • ACL β€” IP allowlist management with structured 409 conflict bodies.
  • Authentication β€” switch between Digest, IP-only, or hybrid modes; rotate passwords.

πŸ§ͺ Battle-Tested

  • 101 unit tests at 94%+ line coverage with PHPUnit 10.
  • Mocked Guzzle via GuzzleHttp\Handler\MockHandler β€” every method and every error path exercised, no network in CI.
  • Read-only integration scaffolding gated by VOICETEL_USERNAME / VOICETEL_PASSWORD env vars.

πŸ“¦ Clean Distribution

  • Zero codegen footprint β€” every byte hand-written.
  • Single Composer package, single namespace, no surprise transitive deps beyond Guzzle.

πŸš€ Installation

composer require voicetel/sdk

Requires PHP 8.1 or later and the json extension (bundled with PHP).

🏁 Quickstart

<?php

require __DIR__ . '/vendor/autoload.php';

use VoiceTel\Sdk\Client;

$client = new Client();

// Exchange username + password for an API key (one-time per session)
$client->login(1000000001, 'hunter2');

// Typed responses β€” arrays with documented shapes.
$me = $client->account->get();
printf("Balance: \$%.2f  |  Caller ID: %s\n", $me['cash'], $me['callerId']);

// List your numbers
$list = $client->numbers->list();
foreach ($list['numbers'] as $n) {
    printf(
        "%s  route=%d  cnam=%s  sms=%s\n",
        $n['number'],
        $n['route'],
        $n['cnam'] ? 'yes' : 'no',
        $n['smsEnabled'] ? 'yes' : 'no',
    );
}

Or, if you already have an API key, skip login() and pass it straight to the constructor:

$client = new Client(apiKey: getenv('VOICETEL_API_KEY'));

$coverage = $client->iNumbering->coverage(['state' => 'NJ']);
foreach ($coverage['coverage'] as $bucket) {
    printf("%s-%s: %d TNs available\n", $bucket['npa'], $bucket['nxx'], $bucket['count']);
}

πŸ”‘ Authentication

Every endpoint requires Authorization: Bearer <apikey> except POST /v2.2/account/api-key, which exchanges username + password for a fresh key. $client->login() handles the exchange and installs the returned key on the client.

Re-fetch the API key after any password change β€” the old one is invalidated.

Don't have credentials yet? Get them at voicetel.com/docs/api/v2.2/credentials.

$client = new Client();
$key = $client->login(1000000001, 'hunter2');
// $key is the new 32-hex bearer; the client already has it installed.

πŸ—ΊοΈ Resource Reference

Resource Property on Client Example
Account $client->account $client->account->cdr(1700000000, 1700100000)
ACL $client->acl $client->acl->add(['acl' => [['cidr' => '1.2.3.0/24']]])
Authentication $client->authentication $client->authentication->update(['authType' => 1])
e911 $client->e911 $client->e911->validate(['address1' => '1 Way', ...])
Gateways $client->gateways $client->gateways->list()
iNumbering $client->iNumbering $client->iNumbering->searchInventory(['npa' => 201])
Lookups $client->lookups $client->lookups->lrn('2015551234', '2125550000')
Messaging $client->messaging $client->messaging->send(['fromNumber' => ..., 'toNumber' => ..., 'text' => ...])
Numbers $client->numbers $client->numbers->assignCampaign('2015551234', ['campaignId' => 'CXXXXXX'])
Support $client->support $client->support->create(['subject' => '...', 'message' => '...'])

Notes on payload shape

  • messaging->send() uses the wire field names fromNumber and toNumber β€” pass them exactly as shown.
  • support->create() / support->get() return a conversation whose number field is a ticket sequence integer (e.g. 1015), not a phone number β€” keep that distinction in mind everywhere else in this API where number is a 10-digit TN.
  • LIDB endpoints (numbers->setLidb()) use the spelling Lidb consistently β€” the legacy Libd typo from earlier spec drafts has been corrected.
  • iNumbering->portAvailability() includes the v2.2.10 fields localRoutingNumber and rateCenterTier alongside the original number, portable, losingCarrier, and reason.
  • DELETE endpoints generally return 204 No Content β€” the corresponding methods return void. Three endpoints intentionally return a body and an array: acl->remove(), numbers->unassignCampaign(), and numbers->bulkUnassignCampaign().

🚨 Error Handling

All HTTP errors throw VoiceTel\Sdk\ApiError. Inspect kind, statusCode, code(), or body:

Kind HTTP status
ErrorKind::BadRequest 400
ErrorKind::Authentication 401
ErrorKind::PermissionDenied 403
ErrorKind::NotFound 404
ErrorKind::Conflict 409
ErrorKind::RateLimit 429
ErrorKind::Server 5xx
ErrorKind::Unknown other / transport
use VoiceTel\Sdk\ApiError;
use VoiceTel\Sdk\ErrorKind;

try {
    $n = $client->numbers->get('9999999999');
} catch (ApiError $e) {
    match ($e->kind) {
        ErrorKind::NotFound  => print "That number isn't on your account.\n",
        ErrorKind::RateLimit => print "Slow down β€” backoff and retry.\n",
        default              => throw $e,
    };
}

Or use the helper predicates:

catch (ApiError $e) {
    if ($e->isNotFound())   { /* ... */ }
    if ($e->isRateLimit())  { /* ... */ }
    if ($e->isConflict())   {
        // $e->body is the structured AclConflictData / AuthPutConflictData payload.
    }
}

⏱️ Rate Limits

These endpoints are limited to 6 requests per hour per IP:

  • account/info ($client->account->get())
  • account/cdr
  • account/recurring-charges
  • account/payments
  • account/registration
  • account/api-key ($client->login())

The SDK automatically retries 429 responses with Retry-After honored, up to maxRetries (default 2). To bump it:

$client = new Client(
    apiKey: getenv('VOICETEL_API_KEY'),
    maxRetries: 4,
    timeout: 60.0,
);

πŸ› οΈ Development

git clone https://github.com/voicetel/php-sdk
cd php-sdk

# Install dependencies
composer install

# Run unit tests
vendor/bin/phpunit --testsuite unit

# With coverage (needs Xdebug or PCOV)
XDEBUG_MODE=coverage vendor/bin/phpunit --testsuite unit --coverage-text

# Static analysis
vendor/bin/phpstan analyse

# Run read-only integration tests against a real account
cp .env.example .env  # populate VOICETEL_USERNAME / VOICETEL_PASSWORD
set -a; source .env; set +a
vendor/bin/phpunit --testsuite integration

πŸ“– API Documentation

πŸ™Œ Contributors

Contributions welcome. Open an issue describing the change, or send a pull request against main.

πŸ’– Sponsors

Sponsor Contribution
VoiceTel Communications Primary development and production hosting

πŸ“„ License

This project is licensed under the MIT License β€” see the LICENSE file for details.

About

Official PHP SDK for the VoiceTel REST API

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages