keboola / php-api-client-base
Shared base for Keboola service API clients (transport, auth, retry)
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.8
- psr/http-message: ^1.0|^2.0
- psr/log: ^1.0|^2.0|^3.0
- webmozart/assert: ^1.11
Requires (Dev)
- keboola/coding-standard: ^15.0
- phpstan/phpstan: ^1.10
- phpstan/phpstan-phpunit: ^1.3
- phpstan/phpstan-webmozart-assert: ^1.2
- phpunit/phpunit: ^9.6
- sempro/phpunit-pretty-print: ^1.4
This package is auto-updated.
Last update: 2026-06-22 11:18:13 UTC
README
Shared base for building PHP clients for Keboola services (Storage, Manage, Vault, Git Service, Sandboxes, Sync Actions, Job Queue, …). It is not a general-purpose HTTP client — it encodes Keboola platform conventions: the Keboola authentication headers, retry behavior, JSON handling, and error normalization that every Keboola service client needs.
Used by keboola/vault-api-client, keboola/sandboxes-service-api-client,
keboola/git-service-api-client, keboola/sync-actions-client,
keboola/azure-api-client, and new Keboola service clients.
Installation
composer require keboola/php-api-client-base
What it provides
ApiClient— Guzzle wrapper with per-request auth, retry, logging, and response-to-model mapping. Constructed asnew ApiClient($baseUrl, $authenticator, $options, errorMessageResolver: ..., retryableStatusCodes: [...]). The authenticator is required; passnew NoAuthAuthenticator()for unauthenticated clients.errorMessageResolveraccepts a?ErrorMessageResolverInterfaceinstance; whennull, the shippedDefaultErrorMessageResolver(which extractserrorormessagefrom JSON bodies) is used automatically.retryableStatusCodesareApiClientconstructor arguments supplied by the service facade (they describe the service's API contract, not caller preferences).ApiClientOptions— retries, timeouts, logger (no auth, no error resolver — the authenticator is a first-classApiClientconstructor argument; the error resolver and retryable codes are alsoApiClientconstructor arguments).Auth\RequestAuthenticatorInterface+ ready authenticators for the Keboola auth schemes:StorageApiTokenAuthenticator(X-StorageApi-Token),ManageApiTokenAuthenticator(X-KBC-ManageApiToken),KeboolaServiceAccountAuthenticator(projected SA token →X-Kubernetes-Authorization),NoAuthAuthenticator(explicit no-op for unauthenticated calls).ErrorMessageResolverInterface,DefaultErrorMessageResolver,RetryDecider,Json,ResponseModelInterface,Exception\ClientException.
Building a Keboola service client
Compose an ApiClient inside your service facade and map responses to models:
use GuzzleHttp\Psr7\Request; use Keboola\ApiClientBase\ApiClient; use Keboola\ApiClientBase\ApiClientOptions; use Keboola\ApiClientBase\Auth\StorageApiTokenAuthenticator; use Keboola\ApiClientBase\ErrorMessageResolverInterface; use Keboola\ApiClientBase\Json; use Keboola\ApiClientBase\ResponseModelInterface; final class WidgetModel implements ResponseModelInterface { public function __construct(public readonly string $id) {} public static function fromResponseData(array $data): static { \assert(is_string($data['id'])); return new self($data['id']); } } final class MyServiceErrorResolver implements ErrorMessageResolverInterface { public function __invoke(string $responseBody, int $statusCode): ?string { /** @var array{error?: string} $data */ $data = json_decode($responseBody, true) ?? []; return isset($data['error']) && $data['error'] !== '' ? $data['error'] : null; } } final class MyServiceClient { private ApiClient $apiClient; public function __construct( string $baseUrl, StorageApiTokenAuthenticator $authenticator, ?ApiClientOptions $options = null, ) { $this->apiClient = new ApiClient( $baseUrl, $authenticator, $options, errorMessageResolver: new MyServiceErrorResolver(), retryableStatusCodes: [429], ); } public function createWidget(string $name): WidgetModel { return $this->apiClient->sendRequestAndMapResponse( new Request('POST', 'widgets', ['Content-Type' => 'application/json'], Json::encodeArray(['name' => $name])), WidgetModel::class, ); } } $client = new MyServiceClient( 'https://my-service.keboola.com', new StorageApiTokenAuthenticator($storageApiToken), new ApiClientOptions(backoffMaxTries: 3), );
Authentication
Pick the authenticator matching the service's scheme, or implement
RequestAuthenticatorInterface for a service-specific scheme (e.g. azure's
OAuth).
KeboolaServiceAccountAuthenticator re-reads the projected SA token on every
request, so kubelet-rotated tokens are picked up automatically. The read is
hardened against the rotation race (read-first, clear PHP's stat cache and
re-check on failure, then retry empty/failed reads with bounded exponential
backoff — ~1.24 s over 5 retries by default, tunable via the maxReadAttempts
and retryBaseDelayMicroseconds constructor arguments).
License
MIT