Connect Any App
Every CelerSearch instance runs Meilisearch and speaks its standard API, so the official SDKs and any HTTP client work as they are. You need two values: the endpoint URL and the API key.
1. Get your connection details
In app.celersearch.com, open your instance. The Connection details card shows:
- Endpoint URL: your instance's
https://address - API key: click the eye icon to reveal it, or copy it directly
Store both as environment variables on your server:
CELERSEARCH_URL=https://your-endpoint-url
CELERSEARCH_API_KEY=your-api-key
The API key has full access
The instance API key is the instance's master key: it can read, change and delete everything. Keep it on your server, in environment variables or a secrets manager, and never ship it in browser or mobile app code. If it leaks, contact us and we'll rotate it.
2. Check the connection
curl -H "Authorization: Bearer $CELERSEARCH_API_KEY" "$CELERSEARCH_URL/health"
# {"status":"available"}
Every request needs the Authorization: Bearer header, including /health,
which is public on a self-hosted Meilisearch.
3. Index and search
The examples below add two documents to a movies index (created
automatically on the first write) and run a search with a typo in it.
JavaScript / TypeScript
npm install meilisearch
import { Meilisearch } from 'meilisearch'
const client = new Meilisearch({
host: process.env.CELERSEARCH_URL,
apiKey: process.env.CELERSEARCH_API_KEY,
})
const movies = client.index('movies')
// Writes are asynchronous tasks; waitTask() resolves once it's processed.
await movies.addDocuments([
{ id: 1, title: 'Carol', genres: ['Romance', 'Drama'] },
{ id: 2, title: 'Wonder Woman', genres: ['Action', 'Adventure'] },
]).waitTask()
const { hits } = await movies.search('wondr woman')
console.log(hits)
PHP
composer require meilisearch/meilisearch-php guzzlehttp/guzzle http-interop/http-factory-guzzle:^1.0
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Meilisearch\Client;
$client = new Client(getenv('CELERSEARCH_URL'), getenv('CELERSEARCH_API_KEY'));
$movies = $client->index('movies');
$task = $movies->addDocuments([
['id' => 1, 'title' => 'Carol', 'genres' => ['Romance', 'Drama']],
['id' => 2, 'title' => 'Wonder Woman', 'genres' => ['Action', 'Adventure']],
]);
$client->waitForTask($task['taskUid']);
print_r($movies->search('wondr woman')->getHits());
Python
pip install meilisearch
import os
import meilisearch
client = meilisearch.Client(os.environ["CELERSEARCH_URL"], os.environ["CELERSEARCH_API_KEY"])
movies = client.index("movies")
task = movies.add_documents([
{"id": 1, "title": "Carol", "genres": ["Romance", "Drama"]},
{"id": 2, "title": "Wonder Woman", "genres": ["Action", "Adventure"]},
])
client.wait_for_task(task.task_uid)
print(movies.search("wondr woman")["hits"])
Other languages
Official Meilisearch SDKs also exist for Go, Ruby, Rust, Java, .NET, Swift and Dart. Configure them the same way: the endpoint URL is the host and the API key is the key. Plain HTTP works too; the Meilisearch API reference applies as written.
Search from the browser
Because the API key has full access, browser search goes through your backend. A small endpoint receives the visitor's query, searches with the key on the server, and returns only what you choose to expose:
import express from 'express'
import { Meilisearch } from 'meilisearch'
const client = new Meilisearch({
host: process.env.CELERSEARCH_URL,
apiKey: process.env.CELERSEARCH_API_KEY,
})
const app = express()
app.get('/api/search', async (req, res) => {
const { hits } = await client.index('movies').search(String(req.query.q ?? ''), {
limit: 20,
attributesToRetrieve: ['id', 'title', 'genres'],
})
res.json(hits)
})
app.listen(3000)
const hits = await fetch(`/api/search?q=${encodeURIComponent(query)}`).then((r) => r.json())
Your endpoint decides which index and fields visitors can reach, the same
job a search-only key does elsewhere. Building with InstantSearch? The
Next.js guide shows a proxy that works with
instant-meilisearch.
Custom API keys and tenant tokens
Keys you create with the /keys endpoint, and tenant tokens, can't be used to
connect to a CelerSearch instance yet: requests that use them are rejected with
401. Use the instance API key from your backend, as shown above.
How it differs from self-hosted Meilisearch
- Authentication: send the instance API key as
Authorization: Bearer <key>on every request. - Dumps and snapshots:
POST /dumpsandPOST /snapshotsare disabled. Your data is protected by encrypted backups you manage from the portal. - Engine version: you choose it and apply upgrades from the portal when you're ready.
- Document limit: your plan sets how many documents the instance holds across all indexes. Searches are always unlimited.
When you reach the document limit
Requests that add or update documents (POST or PUT on
/indexes/{uid}/documents) are refused with 429:
{
"error": "document_quota_exceeded",
"message": "Document quota exceeded for this instance",
"current_documents": 100000,
"max_documents": 100000
}
Searches, reads and deletions keep working. Delete documents or move to a larger plan to write again. The document count refreshes periodically, so after deleting documents it can take a few minutes before writes are accepted again.
Responses from the platform
These come from CelerSearch rather than from Meilisearch, so they use error
and message fields instead of Meilisearch's usual error object. The SDKs raise
them as API errors with the HTTP status.
| Status | error | Meaning |
|---|---|---|
401 | missing_api_key | No Authorization: Bearer header |
401 | invalid_api_key | The key isn't an instance API key |
403 | endpoint_disabled | Dumps and snapshots are managed for you |
429 | document_quota_exceeded | The plan's document limit is reached |
503 | instance_stopped | The instance isn't running |
Next steps
- Framework guides: Laravel Scout, Next.js, Ruby on Rails, Strapi
- Moving an existing index? See Migrate to CelerSearch
- Choosing a plan? Compare document limits on Pricing