A PSR-compatible PHP client for the Searchcraft API.
composer require searchcraft/searchcraft-phpYou will also need to install a PSR-18 compatible HTTP client, such as Guzzle.
composer require guzzlehttp/guzzle http-interop/http-factory-guzzle:^1.0The client can be initialized with different types of API keys, depending on your access requirements:
use Searchcraft\Searchcraft;
// Using an admin key (full access)
$searchcraft_full = new Searchcraft('your-admin-key');
// Using a read-only key (search and read operations only)
$searchcraft_reader = new Searchcraft('your-read-key', Searchcraft::KEY_TYPE_READ);
// Using an ingest key (document operations only)
$searchcraft_ingestion = new Searchcraft('your-ingest-key', Searchcraft::KEY_TYPE_INGEST);By default, the client connects to http://localhost:8000. To use a different endpoint such as a Searchcraft Cloud cluster:
// Replace with your cluster endpoint
$searchcraft = new Searchcraft(
'your-api-key',
Searchcraft::KEY_TYPE_ADMIN,
'https://yourcluster.io'
);The client uses PSR-18 HTTP Client discovery to find an available HTTP client. You can also provide your own:
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
$httpClient = new Client();
$requestFactory = new HttpFactory();
$streamFactory = new HttpFactory();
$searchcraft = new Searchcraft(
'your-api-key',
Searchcraft::KEY_TYPE_ADMIN,
'https://api.searchcraft.io/v1',
$httpClient,
$requestFactory,
$streamFactory
);Searchcraft PHP Client does not include a specific HTTP client in its require dependencies but Guzzle is recommended. You will need to install one in order to use the Searchcraft client.
Search operations require an admin key or read key.
// Simple search query
$results = $searchcraft->search()->query('my_index', 'search term');
// Search with additional parameters
$results = $searchcraft->search()->query('my_index', 'search term', [
'limit' => 20,
'offset' => 0,
'sort' => 'price:asc',
'mode' => 'fuzzy'
]);
// Fuzzy search (default)
$results = $searchcraft->search()->query('my_index', 'search term');
// Explicit fuzzy search
$results = $searchcraft->search()->query('my_index', 'search term', ['mode' => 'fuzzy']);
// Exact search
$results = $searchcraft->search()->query('my_index', 'search term', ['mode' => 'exact']);// Search across all indexes in a federation using federatedQuery
$searchResults = $searchcraft->search()->federatedQuery('my_federation', 'breaking news', [
'limit' => 20,
'offset' => 0,
'mode' => 'fuzzy'
]);
// Federation search with additional options
$searchResults = $searchcraft->search()->federatedQuery('my_federation', 'search term', [
'limit' => 50,
'offset' => 10,
'order_by' => 'publishedAt',
'sort' => 'desc',
'occur' => 'should',
'mode' => 'exact'
]);Index administration operations require an admin key.
$indexes = $searchcraft->index()->listIndexes();$indexDetails = $searchcraft->index()->getIndex('products');$newIndex = $searchcraft->index()->createIndex('blog', [
'index' => [
'name' => 'blog',
'language' => 'en',
'search_fields' => ['title', 'content', 'tags'],
'fields' => [
'id' => [
'type' => 'text',
'required' => true,
'stored' => true,
'indexed' => false
],
'title' => [
'type' => 'text',
'stored' => true
],
'content' => [
'type' => 'text',
'stored' => true
],
'tags' => [
'type' => 'text',
'stored' => true,
'multi' => true
],
'category' => [
'type' => 'facet',
'stored' => true
],
'publishedAt' => [
'type' => 'datetime',
'fast' => true,
'stored' => true,
'indexed' => true
]
],
'weight_multipliers' => [
'title' => 2.0,
'tags' => 1.0,
'content' => 0.6
]
]
]);Note if you are not adding, removing or changing properties of schema fields will likely want to use the PATCH operation instead. An update request will remove existing documents but for patchable updates your index is not emptied. See the docs for details on which properties are patchable.
$updatedIndex = $searchcraft->index()->updateIndex('blog', [
'index' => [
'name' => 'blog',
'language' => 'en',
'search_fields' => ['title', 'content', 'tags', 'summary'],
'fields' => [
'id' => [
'type' => 'text',
'required' => true,
'stored' => true,
'indexed' => false
],
'title' => [
'type' => 'text',
'stored' => true
],
'content' => [
'type' => 'text',
'stored' => true
],
'summary' => [
'type' => 'text',
'stored' => true
],
'tags' => [
'type' => 'text',
'stored' => true,
'multi' => true
],
'category' => [
'type' => 'facet',
'stored' => true
],
'publishedAt' => [
'type' => 'datetime',
'fast' => true,
'stored' => true,
'indexed' => true
]
],
'weight_multipliers' => [
'title' => 2.0,
'content' => 1.0,
'summary' => 1.5
]
]
]);$patchedIndex = $searchcraft->index()->patchIndex('blog', [
'search_fields' => ['title', 'content', 'tags', 'summary'],
'weight_multipliers' => [
'title' => 3.0,
'content' => 1.0,
'summary' => 1.5,
'tags' => 0.8
],
'language' => 'en',
'time_decay_field' => 'publishedAt',
'auto_commit_delay' => 2,
'exclude_stop_words' => true
]);$result = $searchcraft->index()->deleteIndex('my-index');Document operations require an admin key or ingest key.
$result = $searchcraft->index()->addDocuments('products', [
[
'id' => '1',
'name' => 'Smartphone X',
'price' => 699.99,
'category' => 'Electronics',
'brand' => 'BrandName'
],
[
'id' => '2',
'name' => 'Laptop Pro',
'price' => 1299.99,
'category' => 'Electronics',
'brand' => 'BrandName'
]
]);$result = $searchcraft->index()->updateDocuments('products', [
[
'id' => '1',
'price' => 649.99,
'in_stock' => true
]
]);$document = $searchcraft->index()->getDocument('products', '1');$result = $searchcraft->index()->deleteDocuments('products', ['1', '2']);Federation operations allow you to manage federations that combine multiple indexes for cross-index search. Federation administration operations require an admin key, while federation search requires a read key.
// List all federations
$federations = $searchcraft->federation()->listFederations();// Get details of a specific federation
$federation = $searchcraft->federation()->getFederation('galaxy_news_federation');// Get all federations for a specific organization
$organizationFederations = $searchcraft->federation()->getFederationsByOrganization('4');// Create a new federation with weighted index configurations
$newFederation = $searchcraft->federation()->createFederation([
'name' => '4_galaxy_news_test',
'friendly_name' => 'Galaxy News Test Federation',
'created_by' => '1',
'last_modified_by' => '1',
'organization_id' => '4',
'index_configurations' => [
[
'name' => 'news_articles',
'weight_multiplier' => 1.0
],
[
'name' => 'blog_posts',
'weight_multiplier' => 0.8
],
[
'name' => 'press_releases',
'weight_multiplier' => 1.5
]
]
]);// Update an existing federation
$updatedFederation = $searchcraft->federation()->updateFederation('galaxy_news_federation', [
'friendly_name' => 'Updated Galaxy News Federation',
'last_modified_by' => '1',
'organization_id' => '4',
'index_configurations' => [
[
'name' => 'news_articles',
'weight_multiplier' => 1.2
],
[
'name' => 'blog_posts',
'weight_multiplier' => 0.9
],
[
'name' => 'press_releases',
'weight_multiplier' => 1.8
],
[
'name' => 'social_media',
'weight_multiplier' => 0.6
]
]
]);// Delete a federation
$result = $searchcraft->federation()->deleteFederation('old_federation');Requires Searchcraft Engine 0.10.0 or later.
// Returns whether AI features are enabled and which pieces
// (LLM provider, model, and search summary config) are configured.
$capabilities = $searchcraft->index()->getCapabilities('blog');The index must have ai_enabled: true and a valid ai.search_summary
configuration. The engine streams Server-Sent Events: one metadata
event, any number of delta events with content chunks, and a final
done event. searchSummary() returns every parsed event, and you may
optionally pass a callback to react to events as they arrive.
// Collect all events at once
$events = $searchcraft->search()->searchSummary('blog', 'search term', [
'limit' => 5,
'mode' => 'fuzzy',
]);
// Or stream them via a callback
$summaryText = '';
$searchcraft->search()->searchSummary(
'blog',
'search term',
['limit' => 5],
function (string $event, $data) use (&$summaryText) {
if ($event === 'delta' && isset($data['content'])) {
$summaryText .= $data['content'];
}
}
);// Returns all authentication keys scoped to the given index.
$keys = $searchcraft->authentication()->getIndexKeys('blog');The Measure API is primarily used by SDKs and CMS integrations to capture search usage metrics and retrieve dashboard aggregates.
$searchcraft->measure()->trackEvent([
'event_name' => 'document_clicked',
'properties' => [
'searchcraft_index_names' => ['products'],
'external_document_id' => 'sku-42',
'document_position' => 2,
],
'user' => [
'user_id' => 'user-123',
'user_type' => 'authenticated',
],
]);$searchcraft->measure()->trackBatch([
[
'event_name' => 'search_completed',
'properties' => ['searchcraft_index_names' => ['products']],
'user' => ['user_id' => 'user-123'],
],
// ...
]);// All three accept the same optional filter set: organization_id,
// application_id, index_names, user_id, user_type, session_id,
// event_name, date_start, date_end, granularity, rpp, page.
$summary = $searchcraft->measure()->getDashboardSummary(['organization_id' => '4']);
$conversion = $searchcraft->measure()->getDashboardConversion(['date_start' => '2026-01-01']);
$usage = $searchcraft->measure()->getDashboardUsage(['granularity' => 'day']);| Client version | Searchcraft Engine |
|---|---|
| 0.8.x | 0.10.x |
| 0.7.x | 0.7.9 - 0.9.x |
All operations should be wrapped in a try/catch block to handle errors:
use Searchcraft\Exception\SearchcraftException;
try {
$results = $searchcraft->search()->query('products', 'smartphone');
} catch (SearchcraftException $e) {
echo 'Error: ' . $e->getMessage();
}For view the rest of the endpoints and operations, please refer to the full Searchcraft API documentation.
./vendor/bin/pest
