Skip to Content
SDKsPHP

PHP SDK

A PSR-compliant PHP client for the IdentityCall API with Guzzle HTTP support.

Installation

composer require guzzlehttp/guzzle

Quick Start

<?php require 'vendor/autoload.php'; require 'IdentityCallClient.php'; use IdentityCall\Client; $client = new Client(); // List recordings $result = $client->recordings()->list(); foreach ($result['data'] as $recording) { echo "{$recording['id']}: {$recording['name']}\n"; }

Complete Client Implementation

Create a file called IdentityCallClient.php:

IdentityCallClient.php
<?php namespace IdentityCall; use GuzzleHttp\Client as GuzzleClient; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Psr7\MultipartStream; // Exception classes class IdentityCallException extends \Exception { protected $statusCode; protected $response; public function __construct($message, $statusCode = null, $response = null) { parent::__construct($message); $this->statusCode = $statusCode; $this->response = $response; } public function getStatusCode() { return $this->statusCode; } public function getResponse() { return $this->response; } } class AuthenticationException extends IdentityCallException {} class PermissionException extends IdentityCallException {} class NotFoundException extends IdentityCallException {} class ValidationException extends IdentityCallException {} class RateLimitException extends IdentityCallException { protected $retryAfter; public function __construct($message, $retryAfter = 60, $statusCode = null, $response = null) { parent::__construct($message, $statusCode, $response); $this->retryAfter = $retryAfter; } public function getRetryAfter() { return $this->retryAfter; } } // Recordings resource class Recordings { private $client; public function __construct(Client $client) { $this->client = $client; } public function list(int $page = 1, int $perPage = 20): array { return $this->client->request('GET', '/recordings', [ 'query' => ['page' => $page, 'per_page' => $perPage] ]); } public function create(string $filePath, array $options = []): array { $multipart = [ [ 'name' => 'file', 'contents' => fopen($filePath, 'r'), 'filename' => $options['filename'] ?? basename($filePath) ], [ 'name' => 'language', 'contents' => $options['language'] ?? 'en' ] ]; if (isset($options['name'])) { $multipart[] = ['name' => 'name', 'contents' => $options['name']]; } return $this->client->request('POST', '/recordings', [ 'multipart' => $multipart ]); } public function get(int $recordingId): array { return $this->client->request('GET', "/recordings/{$recordingId}"); } public function update(int $recordingId, array $data): array { return $this->client->request('PATCH', "/recordings/{$recordingId}", [ 'json' => $data ]); } public function delete(int $recordingId): void { $this->client->request('DELETE', "/recordings/{$recordingId}"); } public function transcription(int $recordingId): array { return $this->client->request('GET', "/recordings/{$recordingId}/transcription"); } public function results(int $recordingId): array { return $this->client->request('GET', "/recordings/{$recordingId}/results"); } public function summary(int $recordingId): array { return $this->client->request('GET', "/recordings/{$recordingId}/summary"); } public function waitForCompletion(int $recordingId, int $timeout = 600, int $pollInterval = 5): array { $startTime = time(); while (true) { $result = $this->get($recordingId); $recording = $result['data']; if ($recording['status'] === 'completed') { return $recording; } if ($recording['status'] === 'failed') { throw new IdentityCallException('Transcription failed'); } if (time() - $startTime > $timeout) { throw new \RuntimeException('Transcription timed out'); } sleep($pollInterval); } } } // Main client class Client { private const DEFAULT_BASE_URL = 'https://api.identitycall.com/api/v1/public'; private const MAX_RETRIES = 3; private $apiKey; private $baseUrl; private $httpClient; private $recordings; public function __construct(array $options = []) { $this->apiKey = $options['api_key'] ?? getenv('IDENTITYCALL_API_KEY'); if (!$this->apiKey) { throw new \InvalidArgumentException('API key is required'); } $this->baseUrl = $options['base_url'] ?? self::DEFAULT_BASE_URL; $this->httpClient = new GuzzleClient([ 'base_uri' => $this->baseUrl, 'timeout' => $options['timeout'] ?? 30, 'headers' => [ 'Authorization' => "Bearer {$this->apiKey}", 'Accept' => 'application/json' ] ]); $this->recordings = new Recordings($this); } public function recordings(): Recordings { return $this->recordings; } public function request(string $method, string $path, array $options = []): ?array { $attempt = 0; while ($attempt < self::MAX_RETRIES) { try { $response = $this->httpClient->request($method, $path, $options); if ($response->getStatusCode() === 204) { return null; } return json_decode($response->getBody()->getContents(), true); } catch (RequestException $e) { $response = $e->getResponse(); if ($response === null) { throw $e; } $statusCode = $response->getStatusCode(); $data = json_decode($response->getBody()->getContents(), true) ?? []; $errorMessage = $data['error'] ?? 'Unknown error'; // Handle rate limiting if ($statusCode === 429 && $attempt < self::MAX_RETRIES - 1) { $retryAfter = $data['retry_after'] ?? 60; sleep($retryAfter); $attempt++; continue; } // Handle server errors if ($statusCode >= 500 && $attempt < self::MAX_RETRIES - 1) { sleep(pow(2, $attempt)); $attempt++; continue; } // Throw appropriate exception $this->throwException($statusCode, $errorMessage, $data); } $attempt++; } throw new IdentityCallException('Max retries exceeded'); } private function throwException(int $statusCode, string $message, array $data): void { switch ($statusCode) { case 401: throw new AuthenticationException($message, $statusCode, $data); case 403: throw new PermissionException($message, $statusCode, $data); case 404: throw new NotFoundException($message, $statusCode, $data); case 422: throw new ValidationException($message, $statusCode, $data); case 429: $retryAfter = $data['retry_after'] ?? 60; throw new RateLimitException($message, $retryAfter, $statusCode, $data); default: throw new IdentityCallException($message, $statusCode, $data); } } }

Usage Examples

List Recordings

<?php use IdentityCall\Client; $client = new Client(); // Get first page $result = $client->recordings()->list(); foreach ($result['data'] as $recording) { echo "[{$recording['id']}] {$recording['name']} - {$recording['status']}\n"; } // With pagination $result = $client->recordings()->list(2, 50); $meta = $result['meta']; echo "Page {$meta['current_page']} of {$meta['total_pages']}\n";

Upload Recording

<?php $result = $client->recordings()->create('/path/to/call.mp3', [ 'language' => 'en', 'name' => 'Customer Support Call' ]); $recordingId = $result['data']['id']; echo "Uploaded! Recording ID: {$recordingId}\n";

Wait for Transcription

<?php // Upload $result = $client->recordings()->create('/path/to/call.mp3'); $recordingId = $result['data']['id']; // Wait for completion echo "Processing...\n"; $recording = $client->recordings()->waitForCompletion($recordingId); echo "Completed! Duration: {$recording['duration_ms']}ms\n"; // Get transcription $transcription = $client->recordings()->transcription($recordingId); echo $transcription['data']['full_text'];

Get Analysis Results

<?php $results = $client->recordings()->results($recordingId); // Goals echo "Goals:\n"; foreach ($results['data']['goals'] as $goal) { $status = $goal['met'] ? '✓' : '✗'; $score = number_format($goal['score'], 2); echo " {$status} {$goal['goal_name']}: {$score}\n"; } // Keywords echo "\nKeywords:\n"; foreach ($results['data']['keywords'] as $kw) { echo " \"{$kw['keyword_name']}\" - {$kw['count']} mentions\n"; }

Error Handling

<?php use IdentityCall\Client; use IdentityCall\AuthenticationException; use IdentityCall\PermissionException; use IdentityCall\NotFoundException; use IdentityCall\RateLimitException; $client = new Client(); try { $recording = $client->recordings()->get(999999); } catch (NotFoundException $e) { echo "Recording not found\n"; } catch (PermissionException $e) { echo "Permission denied\n"; } catch (AuthenticationException $e) { echo "Invalid API key\n"; } catch (RateLimitException $e) { echo "Rate limited. Retry in {$e->getRetryAfter()} seconds\n"; }

Iterate All Pages

<?php function getAllRecordings(Client $client): array { $allRecordings = []; $page = 1; $perPage = 100; while (true) { $result = $client->recordings()->list($page, $perPage); $allRecordings = array_merge($allRecordings, $result['data']); $meta = $result['meta']; if ($meta['current_page'] >= $meta['total_pages']) { break; } $page++; } return $allRecordings; } // Usage $recordings = getAllRecordings($client); echo "Total recordings: " . count($recordings) . "\n";

Laravel Integration

For Laravel projects, create a service provider:

app/Providers/IdentityCallServiceProvider.php
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use IdentityCall\Client; class IdentityCallServiceProvider extends ServiceProvider { public function register(): void { $this->app->singleton(Client::class, function ($app) { return new Client([ 'api_key' => config('services.identitycall.api_key'), 'base_url' => config('services.identitycall.base_url'), ]); }); } }

Add configuration:

config/services.php
<?php return [ // ... 'identitycall' => [ 'api_key' => env('IDENTITYCALL_API_KEY'), 'base_url' => env('IDENTITYCALL_BASE_URL', 'https://api.identitycall.com/api/v1/public'), ], ];

Use in controllers:

<?php namespace App\Http\Controllers; use IdentityCall\Client; class RecordingController extends Controller { public function __construct( private Client $identityCall ) {} public function index() { $result = $this->identityCall->recordings()->list(); return view('recordings.index', ['recordings' => $result['data']]); } }

Next Steps