elvesora / domain-lookup-php
Framework-independent PHP client for the Elvesora Company Domain Lookup API.
Requires
- php: ^8.2
- ext-json: *
- ext-mbstring: *
- guzzlehttp/guzzle: ^7.9 || ^8.0
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.5 || ^12.0
README
A framework-independent PHP client for resolving a company name to its official domain with the Elvesora Company Domain Lookup API.
Requirements
- PHP 8.2 or later
- PHP
mbstringandjsonextensions - An Elvesora API key
Obtain and manage the key through the Company Domain Lookup documentation. Keep it in server-side configuration; never expose it in browser or mobile client code.
Installation
composer require elvesora/domain-lookup-php
Quick start
<?php require __DIR__.'/vendor/autoload.php'; use Elvesora\DomainLookup\Client; $apiKey = getenv('ELVESORA_DOMAIN_LOOKUP_API_KEY'); if (!is_string($apiKey) || trim($apiKey) === '') { throw new RuntimeException('ELVESORA_DOMAIN_LOOKUP_API_KEY is not configured.'); } $client = new Client($apiKey); $result = $client->lookup( companyName: 'Acme Corporation', additionalContext: 'US software company', ); if ($result->found) { echo $result->domain; // acme.com echo $result->confidence; // 1-100 } else { echo 'No reliable domain was found.'; }
The package does not load a .env file. If your application uses a dotenv library or framework environment loader, initialize it before reading the key and constructing the client.
A not-found lookup is a successful API result: found is false, domain is null, and confidence is 0.
companyName must be non-empty and no longer than 255 characters. Optional additionalContext is trimmed, treats an empty string as absent, and cannot exceed 2,000 characters. The client rejects invalid local input before sending an HTTP request, so those local failures consume no lookup credit.
To validate the API key without consuming lookup allowance:
$health = $client->ping(); echo $health->status; // ok
Result fields
DomainLookupResult exposes readonly properties for:
companyName,normalizedCompanyName, andmessagedomain,found,confidence, andisLivelinkedinUrl,industry,subIndustry, andsectorreasons,lowerReasons, andcachedremainingandlimitfor subscription usagerequestIdfor support and trace correlation
Use $result->toArray() or json_encode($result) when an array or JSON payload is more convenient.
Errors
use Elvesora\DomainLookup\Exception\AuthenticationException; use Elvesora\DomainLookup\Exception\DomainLookupException; use Elvesora\DomainLookup\Exception\UsageLimitException; use Elvesora\DomainLookup\Exception\ValidationException; try { $client = new Client($apiKey); $result = $client->lookup('Acme Corporation'); } catch (\InvalidArgumentException $exception) { // Invalid local configuration, lookup input, timeout, base URL, or request ID. } catch (AuthenticationException $exception) { // The API rejected an invalid or revoked API key. } catch (ValidationException $exception) { // The API returned HTTP 422 validation errors. $errors = $exception->errors(); } catch (UsageLimitException $exception) { $limit = $exception->limit(); $remaining = $exception->remaining(); } catch (DomainLookupException $exception) { if ($exception->retryable) { $retryAfter = $exception->retryAfter; } $requestId = $exception->requestId; }
Exception reference
| Exception | When it is thrown |
|---|---|
\InvalidArgumentException |
Empty or invalid local configuration, lookup input, or request ID; no HTTP request is sent. |
AuthenticationException |
The API returns HTTP 401 for an invalid or revoked key. |
ValidationException |
The API returns HTTP 422. Use errors() for field-level validation messages. |
UsageLimitException |
The API returns HTTP 429. Use limit() and remaining() for available quota metadata. |
ApiException |
The API returns another non-success HTTP response. |
InvalidResponseException |
The API response is not valid JSON, is not a JSON object, or violates the expected result contract. |
TransportException |
The HTTP client cannot complete the request because of a connection, DNS, TLS, or similar transport failure. |
All SDK exceptions extend DomainLookupException. It exposes readonly statusCode, errorType, retryable, retryAfter, responseBody, and requestId properties. Constructor and local input failures use PHP's native \InvalidArgumentException instead. API keys are never added to exception messages.
Configuration
$client = new Client( apiKey: $apiKey, baseUrl: 'https://prospecting.elvesora.com/api', timeout: 100, connectTimeout: 10, userAgent: 'MyApplication/1.0', );
The default customer endpoint is https://prospecting.elvesora.com/api/prospecting/company. HTTP and HTTPS custom base URLs are accepted so local and test environments can use the same client.
Timeout values are seconds and must be greater than zero. connectTimeout is capped internally at the total timeout. A custom base URL must be an absolute HTTP or HTTPS URL with a host and cannot contain embedded credentials, a query string, or a fragment. The user agent must be a non-empty string.
You may pass a custom Guzzle client as the second constructor argument. This is useful for shared handlers, proxies, observability middleware, and deterministic tests.
Request IDs
Every lookup sends an X-Request-Id. The client generates one by default, or you can propagate your own trace identifier:
$result = $client->lookup('Acme Corporation', requestId: 'request-01JABC123XYZ');
The response request ID is available on the result and all SDK exceptions.
A custom request ID must be 8 to 128 characters and may contain only letters, numbers, dots, underscores, colons, and hyphens. The SDK throws InvalidArgumentException before the request when a custom value is invalid. When no value is supplied, the SDK generates a valid identifier automatically.
Retries and credits
The client does not retry automatically. Local validation failures do not reach the API and consume no credit. After an authenticated lookup passes the usage-limit check, completed matches, no-match results, cached results, server-side validation errors, and retryable 502 or 503 responses consume one credit. A request blocked with HTTP 429 consumes no credit. X-Request-Id is a tracing value rather than an idempotency key; inspect retryable and retryAfter, then make any retry decision explicitly.
Development
composer install composer check
The test suite uses mocked HTTP responses and sends no requests to the live Elvesora API.
License
MIT. See LICENSE.