The Idempotency-Key header
POST /api/v2/research accepts an optional Idempotency-Key header. Send a fresh UUID per logical request when you need retry safety — the server dedupes retries and returns the same job_id.
bash
curl -X POST "https://api.grep.ai/api/v2/research" \
-H "Authorization: Bearer $GREP_API_KEY" \
-H "Idempotency-Key: 8b9c1f24-3c1e-4a8d-9f7b-2a6e1c4d5b8e" \
-H "Content-Type: application/json" \
-d '{"question":"Due diligence on Stripe","effort":"medium"}'Replay semantics
If a request fails partway (timeout, connection drop), retry with the same key. The server returns the original committed response — same job_id, same body. No duplicate jobs are created.
bash
# Same key + same body → same job_id, no new work scheduled.
curl -X POST "https://api.grep.ai/api/v2/research" \
-H "Authorization: Bearer $GREP_API_KEY" \
-H "Idempotency-Key: 8b9c1f24-3c1e-4a8d-9f7b-2a6e1c4d5b8e" \
-H "Content-Type: application/json" \
-d '{"question":"Due diligence on Stripe","effort":"medium"}'
# Returns identical envelope as the original call:
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed"
}Body-hash matching
Replay only succeeds if the request body matches the original. The server hashes the JSON body and compares — if you change the body but reuse the key, the request is rejected with 409 idempotency_key_reuse_mismatch. This protects against accidental key reuse across different operations.
TTL windows
After the window expires, the same key can be reused for a fresh job. In practice, generate a new UUID per request and you'll never hit the boundary.
| State | Replay window |
|---|---|
| Committed | 24 hours after the job terminates |
| Pending | 1 hour while the job is in flight |
409 conflict codes
Three distinct 409 codes you might see when reusing a key: Same key, different request body. The server rejects rather than silently overwrite — you almost certainly meant to use a fresh key. Same key while the original job is still in progress. Retry the GET on the original job_id instead of POSTing again. Key was valid but the TTL elapsed. Generate a new key and try again.