# Client Create and configure the client, and read the metadata of every API response. `Synthient\Client` is a `final` class. Create one and reuse it for every request. Constructing it makes no requests, and it has no `close()` method. ## Constructor Every argument is optional, so pass the ones you need by name. ```php public function __construct( #[\SensitiveParameter] ?string $apiKey = null, string $baseUrl = self::DEFAULT_BASE_URL, int $maxRetries = 2, float $connectTimeout = 10.0, float $timeout = 60.0, ?ClientInterface $httpClient = null, ?string $userAgent = null, ?Closure $responseHook = null, ) ``` - `apiKey` `?string` — The API key. When it is `null`, the key is read from the `SYNTHIENT_API_KEY` environment variable. Surrounding whitespace is trimmed. An empty key, or one containing anything other than printable ASCII without spaces, throws `\InvalidArgumentException`. - `baseUrl` `string` — The API base URL, including the version path. The default is `Client::DEFAULT_BASE_URL`. It must be an `http` or `https` URL with a host and no query, fragment, or credentials. - `maxRetries` `int` — How many times a failed request is retried. The default is `2`, `0` disables retries, and a negative value throws. See [Retries and timeouts](https://docs.synthient.com/sdks/php/errors#retries-and-timeouts). - `connectTimeout` `float` — Seconds to wait for a connection. The default is `10.0`, and it must be at least `0.001`. Guzzle's stream handler, which serves streams, downloads, and every request when the cURL extension is missing, ignores it and waits up to `timeout` for the connection instead. - `timeout` `float` — Seconds each attempt waits for a whole response, or for the next data on a stream or download. The default is `60.0`, and it must be at least `0.001`. Retries get a fresh timeout, so it does not bound a whole call. - `httpClient` `?ClientInterface` — A Guzzle client (`GuzzleHttp\ClientInterface`), for proxies, TLS settings, or a custom handler. See the notes below. - `userAgent` `?string` — Appended to the `User-Agent` header, such as `"my-app/1.2"`. The header starts with `synthient-php/` followed by the SDK version, `Client::VERSION`. It must be printable ASCII and not blank. - `responseHook` `(Closure(ResponseMetadata): void)|null` — Called with every API response. See [Response metadata](#response-metadata). ```php $client = new Synthient\Client( maxRetries: 4, userAgent: 'my-app/1.0', ); ``` ```php $client = new Synthient\Client( httpClient: new GuzzleHttp\Client(['proxy' => 'http://proxy.internal:3128']), ); ``` - **Input:** An invalid argument throws `\InvalidArgumentException`. - **Security:** `#[\SensitiveParameter]` keeps the key out of stack traces. - **HTTP client:** A Guzzle client passed as `httpClient` keeps its defaults, such as `proxy`, `verify`, and `cert`, except that the SDK sets `allow_redirects`, `http_errors`, `stream`, and the timeouts on every request. Export downloads drop the client's default headers, cookies, and auth. The client must not retry requests or set a default query. - **Connection:** On billed lookups and `health()` the SDK adds `CURLOPT_FRESH_CONNECT` to the client's `curl` option. Those requests are sent without it through Guzzle's stream handler, which never reuses connections, and throw `\InvalidArgumentException` through a client that requires persistent cURL sharing. - **Streaming:** Streams and downloads need a handler that streams response bodies. Guzzle's default handler does only when the `allow_url_fopen` ini setting is on. With the SDK's default HTTP client, streams and downloads throw `SynthientException` before sending a request when it is off. The SDK checks the setting only for its own default client, so through a client passed as `httpClient` a stream without it buffers until `timeout` runs out. ## Constants - `Client::VERSION` `string` — The SDK version, such as `"1.0.0"`. It is sent in the `User-Agent` header. - `Client::DEFAULT_BASE_URL` `string` — `"https://api.synthient.com/api/v4"`, the base URL of the Synthient HTTP API. - `Client::MAX_BATCH_SIZE` `int` — `1000`, the most addresses `lookupIps()` accepts in one call. ## Response metadata `responseHook` is called with a `ResponseMetadata` after every API response. ```php use Synthient\ResponseMetadata; $client = new Synthient\Client( responseHook: function (ResponseMetadata $meta): void { if ($meta->rateLimit !== null) { echo $meta->statusCode, ' ', $meta->requestId, ' ', $meta->rateLimit->remaining, ' ', $meta->rateLimit->reset, "\n"; } }, ); ``` - **Coverage:** It is called for retries, export pages, stream handshakes, export redirects, errors, and responses that then fail to decode. Storage responses from export downloads are excluded, and a transport failure produces no call. ### ResponseMetadata - `statusCode` `int` — The HTTP status code of the response. - `requestId` `?string` — The `X-Request-Id` header, which support can trace, or `null` if the response has none. - `rateLimit` `?RateLimit` — The rate limit state, or `null` when the response has no complete `RateLimit-*` headers. - `headers` `string[][]` — The response headers. An export redirect's `Location` is a presigned URL, so treat it as a secret. ### RateLimit The rate limit state from the `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset` headers. Limits apply per team and are shared by all of its keys. See [Rate Limits](https://docs.synthient.com/rate-limits). - `limit` `int` — The burst size of the operation's bucket. - `remaining` `int` — The number of requests left in the bucket. - `reset` `int` — Seconds until the bucket is full again. A negative header value is reported as `0`.