Get Search Status
Check if your search is complete and ready to retrieve results.
Poll this endpoint to monitor search progress. When status changes to "completed", fetch your results.
Search Status Flow
Your search moves through these states:
- initiated → Search created, queued for processing (0-1s)
- processing → Search actively running (5-30s depending on algorithm)
- completed → Results ready! ✅ Fetch from
/resultsendpoint - failed → Something went wrong ❌ Check error message
Polling Strategy
Recommended approach:
async function waitForResults(searchId) {
const maxAttempts = 20; // ~60 seconds timeout
for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(`/v1/public/searches/${searchId}`);
const data = await response.json();
if (data.status === 'completed') {
// Success! Get results
return await fetch(`/v1/public/searches/${searchId}/results`);
}
if (data.status === 'failed') {
throw new Error(data.error);
}
// Still processing, wait and retry with backoff
await new Promise(r => setTimeout(r, 2000 + (i * 500)));
}
throw new Error('Search timeout after 60 seconds');
}Response Fields
Always returned:
searchId- Your search identifiersearchGroupId- Group ID if part of comparisonstatus- Current state: "initiated" | "processing" | "completed" | "failed"query- Your original search querysearchType- Algorithm used: "dense" | "sparse" | "hybrid" | "builtin-rerank"createdAt- When search was initiated
When status is "completed":
resultsCount- Number of candidates foundprocessingTimeMs- How long the search took (milliseconds)completedAt- When search finishedresultsUrl- Endpoint to fetch results
When status is "failed":
error- What went wrongerrorRetryable-trueif you should retry,falseif it won't help
When status is "processing":
estimatedCompletion- Rough time remaining
Rate limit
For rate limit, please check the rate limit in the dedicated API documentation section.
Example: Completed Search
GET /v1/public/searches/550e8400-e29b-41d4-a716-446655440000
{
"searchId": "550e8400-e29b-41d4-a716-446655440000",
"searchGroupId": "660e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"query": "senior Python developer",
"searchType": "dense",
"createdAt": "2025-01-15T10:30:00Z",
"resultsCount": 42,
"processingTimeMs": 7834,
"completedAt": "2025-01-15T10:30:08Z",
"resultsUrl": "/v1/public/searches/550e8400-e29b-41d4-a716-446655440000/results"
}Example: Failed Search
GET /v1/public/searches/550e8400-e29b-41d4-a716-446655440000
{
"searchId": "550e8400-e29b-41d4-a716-446655440000",
"searchGroupId": "660e8400-e29b-41d4-a716-446655440000",
"status": "failed",
"query": "senior Python developer",
"searchType": "dense",
"createdAt": "2025-01-15T10:30:00Z",
"error": "No documents found in company database",
"errorRetryable": false
}Processing Times by Algorithm
| Algorithm | Typical Time | Maximum Expected |
|---|---|---|
| Dense | 5-10 seconds | 30 seconds |
| Sparse | 5-10 seconds | 30 seconds |
| Builtin-Rerank | 10-20 seconds | 30 seconds |
| Hybrid | 15-30 seconds | 45 seconds |
If your search exceeds maximum time: Something likely went wrong. Check the status for error details.
Error Handling
Retryable errors (errorRetryable: true):
- Temporary service issues
- Lambda timeout (rare, system under load)
- Network connectivity problems
- Rate limiting
Non-retryable errors (errorRetryable: false):
- Invalid query format
- No documents in your database
- Malformed parameters
- Configuration issues
What to do:
- If
errorRetryable: true→ Wait 5-10 seconds and create a new search - If
errorRetryable: false→ Fix the issue (query, params) before retrying
Complete Integration Example
// Step 1: Start search
const searchResponse = await fetch('/v1/public/searches/dense', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: 'senior backend engineer',
top_k: 20
})
});
const { searchId } = await searchResponse.json();
// Step 2: Poll for completion
let completed = false;
let attempts = 0;
while (!completed && attempts < 20) {
const statusResponse = await fetch(
`/v1/public/searches/${searchId}`
);
const status = await statusResponse.json();
if (status.status === 'completed') {
// Step 3: Get results
const resultsResponse = await fetch(
`/v1/public/searches/${searchId}/results`
);
const results = await resultsResponse.json();
console.log(`Found ${results.totalResults} candidates`);
return results;
}
if (status.status === 'failed') {
throw new Error(`Search failed: ${status.error}`);
}
// Wait before next poll
await new Promise(r => setTimeout(r, 3000));
attempts++;
}
throw new Error('Search timeout');Best Practices
Polling:
-
✅ Use exponential backoff to reduce server load
-
✅ Set reasonable timeout (60 seconds recommended)
-
✅ Handle both completed and failed states
-
❌ Don't poll more than once per second
-
Status responses are not cached - always current
Error Responses
| Status Code | Reason | Solution |
|---|---|---|
| 404 | Search not found | Check searchId is correct and belongs to your company |
| 401 | Invalid API key | Verify Authorization header |
| 500 | Server error | Retry after a few seconds |
Security
- Only returns searches belonging to your company
- Requires valid API key
- Search results are private to your organization
API key for public API access. Get yours at https://app.floreal.ai?tab=api
In: header
Path Parameters
uuidResponse Body
curl -X GET "https://api.floreal.ai/v1/public/searches/497f6eca-6276-4993-bfeb-53cbbbba6f08"{
"searchId": "550e8400-e29b-41d4-a716-446655440000",
"searchGroupId": "660e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"query": "senior Python developer",
"searchType": "dense",
"createdAt": "2025-01-15T10:30:00Z",
"resultsCount": 42,
"processingTimeMs": 7834,
"completedAt": "2025-01-15T10:30:08Z",
"resultsUrl": "/v1/public/searches/550e8400-e29b-41d4-a716-446655440000/results",
"error": "No documents found in company database",
"errorRetryable": false,
"estimatedCompletion": "5-10 seconds"
}{
"error": "string",
"message": "string"
}{
"error": "string"
}{
"error": "string",
"message": "string"
}