didww/didww-api-3-php-sdk

PHP SDK for DIDWW API 3

Maintainers

Package info

github.com/didww/didww-api-3-php-sdk

pkg:composer/didww/didww-api-3-php-sdk

Statistics

Installs: 17 899

Dependents: 0

Suggesters: 0

Stars: 12

Open Issues: 0

v7.3.0 2026-03-09 15:26 UTC

README

PHP client for DIDWW API v3.

PHP from Packagist Latest Version on Packagist Tests Coverage

About DIDWW API v3

The DIDWW API provides a simple yet powerful interface that allows you to fully integrate your own applications with DIDWW services. An extensive set of actions may be performed using this API, such as ordering and configuring phone numbers, setting capacity, creating SIP trunks and retrieving CDRs and other operational data.

The DIDWW API v3 is a fully compliant implementation of the JSON API specification.

This SDK uses swisnl/json-api-client for JSON:API serialization and deserialization.

Read more https://doc.didww.com/api

By default, this SDK sends the X-DIDWW-API-Version: 2022-05-10 header with each request.

Requirements

  • PHP 8.2+

Installation

composer require didww/didww-api-3-php-sdk

Usage

$credentials = new Didww\Credentials('YOUR_API_KEY', 'sandbox');
Didww\Configuration::configure($credentials, ['timeout' => 20]);

// Check balance
$balance = Didww\Item\Balance::find()->getData();
echo "Balance: " . $balance->getTotalBalance();

// List DID groups with stock keeping units
$didGroups = Didww\Item\DidGroup::all([
    'include' => 'stock_keeping_units',
    'filter' => ['area_name' => 'Acapulco'],
])->getData();

For more examples visit examples/.

For details on obtaining your API key please visit https://doc.didww.com/api3/configuration.html

Examples

Configuration

// Sandbox
$credentials = new Didww\Credentials('YOUR_API_KEY', 'sandbox');
Didww\Configuration::configure($credentials, ['timeout' => 20]);

// Production
$credentials = new Didww\Credentials('YOUR_API_KEY', 'production');
Didww\Configuration::configure($credentials, ['timeout' => 20]);

Environments

Environment Base URL
production https://api.didww.com/v3
sandbox https://sandbox-api.didww.com/v3

Resources

Read-Only Resources

// Countries
$countries = Didww\Item\Country::all()->getData();
$country = Didww\Item\Country::find('uuid')->getData();

// Regions
$regions = Didww\Item\Region::all()->getData();

// Cities
$cities = Didww\Item\City::all()->getData();

// Areas
$areas = Didww\Item\Area::all()->getData();

// NANPA Prefixes
$prefixes = Didww\Item\NanpaPrefix::all()->getData();

// POPs (Points of Presence)
$pops = Didww\Item\Pop::all()->getData();

// DID Group Types
$types = Didww\Item\DidGroupType::all()->getData();

// DID Groups (with stock keeping units)
$groups = Didww\Item\DidGroup::all(['include' => 'stock_keeping_units'])->getData();

// Available DIDs
$available = Didww\Item\AvailableDid::all([
    'include' => 'did_group.stock_keeping_units',
])->getData();

// Proof Types
$proofTypes = Didww\Item\ProofType::all()->getData();

// Public Keys
$publicKeys = Didww\Item\PublicKey::all()->getData();

// Requirements
$requirements = Didww\Item\Requirement::all()->getData();

// Balance (singleton)
$balance = Didww\Item\Balance::find()->getData();

DIDs

// List DIDs
$dids = Didww\Item\Did::all()->getData();

// Update DID - assign trunk and capacity
$did = Didww\Item\Did::find('uuid')->getData();
$did->setDescription('Updated');
$did->setCapacityLimit(20);
$did->setVoiceInTrunk(Didww\Item\VoiceInTrunk::build('trunk-uuid'));
$did->save();

Dirty-Only PATCH Serialization

When updating resources, the SDK tracks which attributes and relationships have changed since the resource was loaded (or built). Only dirty fields are included in the PATCH request body, reducing payload size and avoiding unintended overwrites.

// Load a DID from the API - all fields are marked as persisted
$did = Didww\Item\Did::find('uuid')->getData();

// Change only the description - only dirty fields are sent
$did->setDescription('New description');
$did = $did->save()->getData(); // reassign to get synced persisted state
// PATCH body: {"data":{"type":"dids","id":"...","attributes":{"description":"New description"}}}

// Build a resource by ID and set a single field
$did = Didww\Item\Did::build('uuid');
$did->setCapacityLimit(10);
$did = $did->save()->getData();
// PATCH body: {"data":{"type":"dids","id":"...","attributes":{"capacity_limit":10}}}

// Explicitly clear a field by setting it to null
$did = Didww\Item\Did::build('uuid');
$did->setDescription(null);
$did = $did->save()->getData();
// PATCH body: {"data":{"type":"dids","id":"...","attributes":{"description":null}}}

// Included resources also start with clean dirty state
$didDocument = Didww\Item\Did::find('uuid', ['include' => 'voice_in_trunk']);
$trunk = $didDocument->getData()->voiceInTrunk()->getIncluded();
// $trunk has persisted state synced - modifying and saving it sends only dirty fields
$trunk->setName('Renamed trunk');
$trunk = $trunk->save()->getData();
// PATCH body: {"data":{"type":"voice_in_trunks","id":"...","attributes":{"name":"Renamed trunk"}}}

Voice In Trunks

use Didww\Enum\CliFormat;
use Didww\Enum\Codec;
use Didww\Enum\MediaEncryptionMode;
use Didww\Enum\SstRefreshMethod;
use Didww\Enum\TransportProtocol;

// Create SIP trunk
$sip = new Didww\Item\Configuration\Sip([
    'host' => 'sip.example.com',
    'port' => 5060,
    'codec_ids' => Didww\Item\Configuration\Base::getDefaultCodecIds(),
    'transport_protocol_id' => TransportProtocol::UDP,
    'sst_refresh_method_id' => SstRefreshMethod::INVITE,
    'media_encryption_mode' => MediaEncryptionMode::DISABLED,
    'rerouting_disconnect_code_ids' => Didww\Item\Configuration\Base::getDefaultReroutingDisconnectCodeIds(),
]);

$trunk = new Didww\Item\VoiceInTrunk();
$trunk->setName('My SIP Trunk');
$trunk->setCliFormat(CliFormat::E164);
$trunk->setRingingTimeout(30);
$trunk->setConfiguration($sip);

$trunkDocument = $trunk->save();
$trunk = $trunkDocument->getData();

// Update trunk
$trunk->setDescription('Updated');
$trunk->save();

// Delete trunk
$trunk->delete();

Voice In Trunk Groups

$group = new Didww\Item\VoiceInTrunkGroup();
$group->setName('Primary Group');
$group->setCapacityLimit(50);
$groupDocument = $group->save();

Voice Out Trunks

use Didww\Enum\OnCliMismatchAction;

$trunk = new Didww\Item\VoiceOutTrunk();
$trunk->setName('My Outbound Trunk');
$trunk->setAllowedSipIps(['0.0.0.0/0']);
$trunk->setOnCliMismatchAction(OnCliMismatchAction::REPLACE_CLI);
$trunk->setDefaultDid(Didww\Item\Did::build('did-uuid'));
$trunkDocument = $trunk->save();

Orders

use Didww\Enum\CallbackMethod;

// Order by SKU
$order = new Didww\Item\Order([
    'allow_back_ordering' => true,
    'items' => [
        new Didww\Item\OrderItem\Did(['sku_id' => 'sku-uuid', 'qty' => 2]),
    ],
]);
$order->setCallbackUrl('https://example.com/callback');
$order->setCallbackMethod(CallbackMethod::POST);
$orderDocument = $order->save();

// Order available DID
$order = new Didww\Item\Order([
    'items' => [
        new Didww\Item\OrderItem\AvailableDid([
            'sku_id' => 'sku-uuid',
            'available_did_id' => 'available-did-uuid',
        ]),
    ],
]);

// Order reserved DID
$order = new Didww\Item\Order([
    'items' => [
        new Didww\Item\OrderItem\ReservationDid([
            'sku_id' => 'sku-uuid',
            'did_reservation_id' => 'reservation-uuid',
        ]),
    ],
]);

// Order capacity
$order = new Didww\Item\Order([
    'items' => [
        new Didww\Item\OrderItem\Capacity([
            'capacity_pool_id' => 'pool-uuid',
            'qty' => 1,
        ]),
    ],
]);

DID Reservations

$reservation = new Didww\Item\DidReservation();
$reservation->setDescription('Reserved for client');
$reservation->setAvailableDid(Didww\Item\AvailableDid::build('available-did-uuid'));
$reservationDocument = $reservation->save();

// Delete reservation
$reservation->delete();

Shared Capacity Groups

$group = new Didww\Item\SharedCapacityGroup();
$group->setName('Shared Group');
$group->setSharedChannelsCount(20);
$group->setCapacityPool(Didww\Item\CapacityPool::build('pool-uuid'));
$groupDocument = $group->save();

Identities

use Didww\Enum\IdentityType;

$identity = new Didww\Item\Identity([
    'first_name' => 'John',
    'last_name' => 'Doe',
    'phone_number' => '12125551234',
    'identity_type' => IdentityType::PERSONAL,
]);
$identity->setCountry(Didww\Item\Country::build('country-uuid'));
$identityDocument = $identity->save();

Addresses

$address = new Didww\Item\Address();
$address->setCityName('New York');
$address->setPostalCode('10001');
$address->setAddress('123 Main St');
$address->setIdentity(Didww\Item\Identity::build('identity-uuid'));
$address->setCountry(Didww\Item\Country::build('country-uuid'));
$addressDocument = $address->save();

Exports

use Didww\Enum\ExportType;

$export = new Didww\Item\Export();
$export->setExportType(ExportType::CDR_IN);
$export->setFilterYear('2025');
$export->setFilterMonth('01');
$exportDocument = $export->save();

// Download the export when completed
$export = $exportDocument->getData();
$export->download('/tmp/export.csv');

Date and Datetime Fields

Date and datetime attributes returned from the API are represented as strings in the underlying JSON. This SDK provides typed getter methods for some known date and datetime attributes; these getters convert those string values to \DateTime instances.

  • Datetime getters — return \DateTime with full timestamp:
    • All getCreatedAt() methods — present on most resources
    • Expiry getters: Did::getExpiresAt(), DidReservation::getExpireAt(), Proof::getExpiresAt(), EncryptedFile::getExpireAt()
  • Date-only getters — return \DateTime with time 00:00:00:
    • Identity::getBirthDate()
  • Getters that intentionally keep strings — these represent dates but still return string values:
    • CapacityPool::getRenewDate()
    • Order item getBilledFrom() / getBilledTo()
$did = Didww\Item\Did::find('uuid')->getData();
echo $did->getCreatedAt()->format('Y-m-d H:i:s');  // e.g. "2024-01-15 10:00:00"
echo $did->getExpiresAt()?->format('Y-m-d');        // null or "2025-01-15"

$identity = Didww\Item\Identity::find('uuid')->getData();
echo $identity->getBirthDate()->format('Y-m-d');    // e.g. "1990-05-20"

Filtering, Sorting, and Pagination

$regionsDocument = Didww\Item\Region::all([
    'filter' => ['country.id' => 'uuid', 'name' => 'Arizona'],
    'include' => 'country',
    'sort' => 'name',
    'page' => ['size' => 25, 'number' => 1],
]);
$regions = $regionsDocument->getData();

Enums

The SDK provides PHP 8.2+ backed enum classes for all API option fields (for example CallbackMethod, IdentityType, OrderStatus, ExportType, CliFormat, OnCliMismatchAction, MediaEncryptionMode, TransportProtocol, Codec, and more).

use Didww\Enum\CallbackMethod;
use Didww\Enum\IdentityType;

$order = new Didww\Item\Order();
$order->setCallbackMethod(CallbackMethod::POST);

$identity = new Didww\Item\Identity();
$identity->setIdentityType(IdentityType::BUSINESS);

All setters accept both enum constants and raw string/integer values for backward compatibility:

use Didww\Enum\OnCliMismatchAction;

// Both are equivalent
$trunk->setOnCliMismatchAction(OnCliMismatchAction::REPLACE_CLI);
$trunk->setOnCliMismatchAction('replace_cli');

Available Enums

Enum Backing Type Values
CliFormat string RAW, E164, LOCAL
IdentityType string PERSONAL, BUSINESS
OrderStatus string PENDING, CANCELED, COMPLETED
CallbackMethod string POST, GET
ExportType string CDR_IN, CDR_OUT
ExportStatus string PENDING, PROCESSING, COMPLETED
AddressVerificationStatus string PENDING, APPROVED, REJECTED
MediaEncryptionMode string DISABLED, SRTP_SDES, SRTP_DTLS, ZRTP
StirShakenMode string DISABLED, ORIGINAL, PAI, ORIGINAL_PAI, VERSTAT
OnCliMismatchAction string SEND_ORIGINAL_CLI, REJECT_CALL, REPLACE_CLI
DefaultDstAction string ALLOW_ALL, REJECT_ALL
VoiceOutTrunkStatus string ACTIVE, BLOCKED
Feature string VOICE_IN, VOICE_OUT, T38, SMS_IN, SMS_OUT
AreaLevel string WORLDWIDE, COUNTRY, AREA, CITY
Codec int TELEPHONE_EVENT(6), G723(7), G729(8), PCMU(9), PCMA(10), ...
TransportProtocol int UDP(1), TCP(2), TLS(3)
RxDtmfFormat int RFC_2833(1), SIP_INFO(2), RFC_2833_OR_SIP_INFO(3)
TxDtmfFormat int DISABLED(0), RFC_2833(1), SIP_INFO_RELAY(2), SIP_INFO_DTMF(4)
SstRefreshMethod int INVITE(1), UPDATE(2), UPDATE_FALLBACK_INVITE(3)
ReroutingDisconnectCode int 47 SIP error codes (56-108, 1505)

File Encryption

The SDK provides an Encrypt utility for encrypting files before upload, using RSA-OAEP + AES-256-CBC (matching DIDWW's encryption requirements).

$fileContents = file_get_contents('/path/to/document.pdf');
$enc = new Didww\Encrypt();
$fingerprint = $enc->getFingerprint();
$encData = $enc->encrypt($fileContents);
$uploadResult = Didww\Item\EncryptedFile::upload($fingerprint, [$encData], ['file description']);

Webhook Signature Validation

Validate incoming webhook callbacks from DIDWW using HMAC-SHA1 signature verification.

$validator = new Didww\Callback\RequestValidator('YOUR_API_KEY');

$valid = $validator->validate(
    $requestUrl,      // full original URL
    $payloadParams,   // array of payload key-value pairs
    $signature         // value of X-DIDWW-Signature header
);

Trunk Configuration Types

Type Class
SIP Didww\Item\Configuration\Sip
PSTN Didww\Item\Configuration\Pstn

Order Item Types

Type Class
DID Didww\Item\OrderItem\Did
Available DID Didww\Item\OrderItem\AvailableDid
Reservation DID Didww\Item\OrderItem\ReservationDid
Capacity Didww\Item\OrderItem\Capacity
Generic Didww\Item\OrderItem\Generic

All Supported Resources

Resource Class Operations
Country Didww\Item\Country list, find
Region Didww\Item\Region list, find
City Didww\Item\City list, find
Area Didww\Item\Area list, find
NanpaPrefix Didww\Item\NanpaPrefix list, find
Pop Didww\Item\Pop list, find
DidGroupType Didww\Item\DidGroupType list, find
DidGroup Didww\Item\DidGroup list, find
AvailableDid Didww\Item\AvailableDid list, find
ProofType Didww\Item\ProofType list, find
PublicKey Didww\Item\PublicKey list, find
Requirement Didww\Item\Requirement list, find
SupportingDocumentTemplate Didww\Item\SupportingDocumentTemplate list, find
Balance Didww\Item\Balance find
Did Didww\Item\Did list, find, update, delete
VoiceInTrunk Didww\Item\VoiceInTrunk list, find, create, update, delete
VoiceInTrunkGroup Didww\Item\VoiceInTrunkGroup list, find, create, update, delete
VoiceOutTrunk Didww\Item\VoiceOutTrunk list, find, create, update, delete
VoiceOutTrunkRegenerateCredential Didww\Item\VoiceOutTrunkRegenerateCredential create
DidReservation Didww\Item\DidReservation list, find, create, delete
CapacityPool Didww\Item\CapacityPool list, find
SharedCapacityGroup Didww\Item\SharedCapacityGroup list, find, create, update, delete
Order Didww\Item\Order list, find, create
Export Didww\Item\Export list, find, create
Address Didww\Item\Address list, find, create, delete
AddressVerification Didww\Item\AddressVerification list, create
Identity Didww\Item\Identity list, find, create, delete
EncryptedFile Didww\Item\EncryptedFile list, find, delete
PermanentSupportingDocument Didww\Item\PermanentSupportingDocument create, delete
Proof Didww\Item\Proof create, delete
RequirementValidation Didww\Item\RequirementValidation create

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/didww/didww-api-3-php-sdk

License

The package is available as open source under the terms of the MIT License.