PHP client for the Datalumo. Bearer authentication, a fully configurable base URL, and SSE streaming for chat.
- PHP >= 8.1
- Composer
guzzlehttp/guzzle ^7.8(installed automatically)
composer require datalumo/php-sdkuse Datalumo\Client;
$client = new Client(
apiKey: 'your_token',
baseUrl: 'http://127.0.0.1:3000',
);
// Create an index and add an item
$client->indexes()->create(['name' => 'docs']);
$client->ingestion()->addItem('docs', [
'id' => 'welcome',
'title' => 'Refund policy',
'searchable_text' => 'Refunds are available within 30 days of purchase.',
]);
// Or add several at once (and pass envelope options like force):
$client->ingestion()->addItems('docs', [
['id' => 'a', 'searchable_text' => '...'],
['id' => 'b', 'searchable_text' => '...'],
], ['force' => true]);
// Search through an app
$results = $client->search()->search('support-bot', [
'query' => 'how do refunds work?',
'k' => 5,
]);All methods return the decoded JSON response as a PHP array (or null for 204 No Content).
The chat endpoint can stream its answer as Server-Sent Events. Use stream() to iterate
events as they arrive, or chat() for a single blocking response.
foreach ($client->chat()->stream('support-bot', ['message' => 'Can I get a refund?']) as $event) {
switch ($event['type']) { // start | delta | step | done | error
case 'delta':
echo $event['text']; // print tokens as they stream
break;
case 'done':
echo "\n";
break;
}
}
// Or, non-streaming:
$answer = $client->chat()->chat('support-bot', ['message' => 'Can I get a refund?']);
echo $answer['answer'];Every HTTP error is raised as a typed exception carrying the parsed error envelope
({ "error": { "code", "message", "details" } }):
use Datalumo\Exception\ApiException;
use Datalumo\Exception\NotFoundException;
use Datalumo\Exception\TransportException;
try {
$client->indexes()->get('missing');
} catch (NotFoundException $e) { // 404
// ...
} catch (ApiException $e) { // any other 4xx/5xx
$e->getHttpStatus(); // e.g. 409
$e->getErrorCode(); // e.g. "conflict"
$e->getDetails(); // free-form details
} catch (TransportException $e) { // connection refused, timeout, TLS, ...
// ...
}| HTTP status | Exception |
|---|---|
| 400 | BadRequestException |
| 404 | NotFoundException |
| 409 | ConflictException |
| 500 | ServerException |
| 501 | NotImplementedException |
| other ≥400 | ApiException (base) |
All of them extend ApiException, which extends DatalumoException. Transport-level
failures throw TransportException. Catch DatalumoException to handle anything the SDK
can throw.
Accessed via $client-><resource>():
| Accessor | Endpoints |
|---|---|
indexes() |
create / list / get / delete indexes |
ingestion() |
add / list / get / delete items, batch ingest, job status |
apps() |
create / list / get / update / delete / restore / widget |
search() |
search within an app |
chat() |
chat (blocking) and stream (SSE) |
summarize() |
summarize results for a query |
analytics() |
record events; queries / clicks / feedback / volume / usage / system |
conversations() |
list / get / delete conversations |
tokens() |
API tokens, widget tokens, publishable keys |
sync() |
create / list / get / update / delete / run sync schedules |
The constructor accepts:
| Argument | Default | Purpose |
|---|---|---|
apiKey |
— (required) | Bearer token |
baseUrl |
— (required) | API base URL |
timeout |
30.0 |
Per-request timeout (seconds) |
headers |
[] |
Extra default headers |
httpClient |
null |
Bring your own GuzzleHttp\ClientInterface |
guzzleConfig |
[] |
Extra Guzzle config (e.g. handler, proxy, verify) |
The SDK is intentionally open for extension: no classes are final, internal helpers are
protected, and you can inject a custom Guzzle client or middleware stack — for logging,
retries, or custom auth — without forking. For example, to add a retry middleware:
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
$stack = HandlerStack::create();
$stack->push(Middleware::retry(/* ... */));
$client = new Client(
apiKey: 'your_token',
baseUrl: 'http://127.0.0.1:3000',
guzzleConfig: ['handler' => $stack],
);composer install
vendor/bin/phpunitTests use Guzzle's MockHandler, so they run without a live server.