froomle / sdk
Server-side Froomle OAuth and Items API primitives
Requires
- php: ^8.1
- ext-mbstring: *
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.1 || ^2.0
- psr/log: ^2.0 || ^3.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
froomle/sdk provides reusable server-side primitives for integrating PHP
applications with Froomle. Drupal modules, WordPress plugins and custom PHP
applications can share this package without inheriting CMS-specific behavior.
The current 0.1.x line provides:
- OAuth 2.0 client-credentials token acquisition for isolated Items and Recommendations connection profiles;
- opaque token caching, refresh skew and injectable cache/lock adapters;
- Items API create, upsert, enable, disable and delete operations;
- PSR-18 HTTP, PSR-17 request/stream and PSR-3 logging integration;
- one forced OAuth refresh after an Items API
401; - bounded binary exponential backoff for transport failures,
429and5xx; - typed results and actionable exception classes.
This is a server-only package. It does not render recommendations, parse or rewrite HTML, buffer application output, set cookies, inject scripts, decode JWT claims or contain Drupal/WordPress-specific integration code.
Requirements
- PHP 8.1 or newer
ext-mbstring- a PSR-18 HTTP client
- PSR-17 request and stream factories
The package deliberately does not force a particular HTTP implementation. Framework integrations should inject the HTTP stack they already use.
Installation
composer require froomle/sdk:^0.1
The 0.1.x API replaces the legacy 0.0.x page-rewriting SDK. Historical
0.0.x releases remain available, but they are not part of this server SDK.
Items API
Create one Items connection profile and inject your PSR implementations:
<?php
use Froomle\Sdk\ClientFactory;
use Froomle\Sdk\ConnectionProfile;
$factory = new ClientFactory($httpClient, $requestFactory, $streamFactory);
$profile = new ConnectionProfile(
'customer-tenant',
ConnectionProfile::ITEMS,
$itemsClientId,
$itemsClientSecret,
);
$items = $factory->items($profile, 'customer-production', 'article');
$result = $items->upsert('article-42', [
'title' => 'Example article',
'tags' => ['news', 'campus'],
'publication_datetime' => '2026-08-12T12:00:00+02:00',
]);
if ($result->statusCode() === 200) {
// The Items API accepted the update.
}
Available operations:
$items->create($payload);
$items->upsert($itemId, $payload);
$items->enable($itemId);
$items->disable($itemId);
$items->delete($itemId);
Every HTTP 2xx response is final success from the client's perspective. The
SDK does not inspect Froomle's downstream processing after the API has accepted
the request.
OAuth profiles
Items and Recommendations credentials must use separate profiles, even when they belong to the same tenant:
$itemsProfile = new ConnectionProfile(
'customer-tenant',
ConnectionProfile::ITEMS,
$itemsClientId,
$itemsClientSecret,
);
$recommendationsProfile = new ConnectionProfile(
'customer-tenant',
ConnectionProfile::RECOMMENDATIONS,
$recommendationsClientId,
$recommendationsClientSecret,
);
$recommendationsTokens = $factory->tokenProvider($recommendationsProfile);
$bearer = $recommendationsTokens->getToken()->value();
The SDK sends only grant_type, client_id and client_secret to the token
endpoint. Tokens are opaque and cache identities keep Items and Recommendations
profiles isolated.
Never log or serialize ConnectionProfile::clientSecret() or
AccessToken::value(). Object debug output redacts both values.
Token persistence and locking
InMemoryTokenStore and InProcessRefreshLock are safe defaults for a simple
PHP process. Long-running or multi-worker applications should provide durable
implementations of:
Froomle\Sdk\OAuth\TokenStoreInterface;Froomle\Sdk\OAuth\RefreshLockInterface.
Drupal, WordPress and other frameworks should adapt their native cache and lock services to these interfaces. Credentials and bearer tokens must remain server-side.
Failures and retries
All SDK exceptions extend Froomle\Sdk\Exception\FroomleException:
AuthenticationException: OAuth credentials or a refreshed token were rejected;ClientRequestException: the Items API returned a final non-4014xx;RetryableException:429or5xxresponses exhausted the retry budget;TransportException: transport failures exhausted the retry budget;ProtocolException: a response or generated contract was invalid.
ClientRequestException and RetryableException expose statusCode().
Retries are bounded and use jittered binary exponential backoff. Applications
can inject a custom RetryPolicy, sleeper and logger through ClientFactory.
Development and release provenance
The package is generated from the shared Froomle SDK source and conformance
fixtures. Its generated protocol runtime is an internal implementation detail;
public integrations should use only Froomle\Sdk\** APIs documented above.
Every distribution contains FROOMLE-PROVENANCE.json, which records the exact
source commit and payload digest. Releases are assembled from a strict
whitelist and verified through a clean Composer consumer before publication.
See CHANGELOG.md for PHP package release notes.
License
froomle/sdk is licensed under the Apache License 2.0. The complete license
text is included in every Composer distribution; see LICENSE.