Grok Chat Result API | Poll an Async Grok Answer
Poll a job POST /twitter/grok/chat/submit started. While it runs you get a 202 with status pending and poll_after_seconds. When it finishes you get a 200 with exactly the body POST /twitter/grok/chat returns plus job_id and status done, and the fields projection works on it. If the chat failed you get the status and typed error grok/chat would have answered, plus job_id and status failed; 504 job_timeout and 503 job_interrupted mean the job did not finish on our side. An unknown job_id, a finished answer older than 15 minutes, or another key's job all return 404. The $0.0040 grok/chat price is charged once, on the first poll that delivers the finished answer; polling it again is free. Cost: Free per call.
GET grok/chat/result polls a job from grok/chat/submit. Pending answers 202 with poll_after_seconds. Done answers 200 with the grok/chat body plus job_id and status. The call is free, and $0.0040 is charged once, on the first poll that delivers the finished answer.
Authorization
bearerAuth Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.
In: header
Query Parameters
The job_id POST /twitter/grok/chat/submit returned, a UUID.
Comma-separated list of dotted field paths to keep in the response (one parameter, never repeated), applied to every object in the returned lists and to nested objects (for example fields=id,text,author.username; the list's own name may prefix a path, fields=tweets.id). A path prefix that lands on an array applies to each element (media.media_url_https). Pagination and envelope keys (next_cursor, cursor, has_more, count, partial, error, message, reason) are always kept. Unknown paths are ignored; up to 50 paths of up to 6 segments. Projection never changes status codes or billing, and applies to data reads only: account, feedback, session status, monitor (other than deliveries), webhook and stream-compat reads return their bodies unchanged.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/grok/chat/result?job_id=5b0f6a52-3c7e-4f1a-9d2b-8e4c6a1f0b37&fields=id%2Ctext%2Ccreated_at%2Cauthor.username"{ "ok": true, "conversation_id": "2088999211077345534", "response_id": "2089001859230978049", "user_response_id": "2089001859230978048", "answer": "Reaction on X is running positive on the on-device model work and negative on the pricing. The liveblog thread and several developer accounts flag the new background-execution API as the change most people expect to ship against first.", "citations": [ { "url": "https://x.com/verge/status/2089000000000000001", "domain": "x.com", "title": "The Verge on X", "snippet": "Everything announced in the keynote, in order." }, { "url": "https://www.theverge.com/wwdc-keynote-liveblog", "domain": "theverge.com", "title": "WWDC keynote liveblog", "snippet": "Live updates as the keynote runs." }, { "url": "https://news.ycombinator.com/item?id=41234567", "domain": "news.ycombinator.com", "title": null, "snippet": "Developer discussion of the background-execution API." } ], "citation_count": 3, "tool_calls": [ { "id": "5f2b8c1a-9d34-4c77-b0e2-6a1f7c3d8e90", "tool": "web_search", "args": { "query": "WWDC keynote reaction developers", "num_results": "15" } } ], "requested_model": "grok-4-auto", "model": "grok-4", "mode": "auto", "job_id": "5b0f6a52-3c7e-4f1a-9d2b-8e4c6a1f0b37", "status": "done"}{ "job_id": "5b0f6a52-3c7e-4f1a-9d2b-8e4c6a1f0b37", "status": "pending", "poll_after_seconds": 3, "created_at": "2026-11-04T18:02:11.482Z"}{ "error": "bad_request", "message": "`job_id` is required: the id POST /twitter/grok/chat/submit returned."}{ "error": "unauthorized", "message": "The API key is missing, malformed, or revoked. Check the Authorization header."}{ "error": "not_found", "message": "No Grok job with this job_id for this API key. Finished results are kept for 900 seconds; submit again if it has expired."}{ "error": "job_interrupted", "message": "The service restarted while this Grok job was running. It was not charged. Submit it again."}{ "error": "job_timeout", "message": "This Grok job did not finish in time and was not charged. Submit it again."}Pricing
| Unit | Price |
|---|---|
| Per call | Free |
Polling is free. The $0.0040 grok/chat price is charged once, on the first poll that delivers a finished answer. Polling the same finished job again returns the same answer and charges nothing, and a pending or failed poll is never charged.
When to use
Call this after Grok Chat: Submit, waiting poll_after_seconds between polls, until you get anything other than a 202. It takes only the job_id and your API key. It sends no prompt of its own, and it cannot start a job.
Notes
- pending answers 202 with poll_after_seconds and a Retry-After header. Poll again after that many seconds.
- done answers 200 with the Grok Chat body plus job_id and status done. The fields projection works on it.
- failed returns the status and typed error Grok Chat would have answered (for example 401, 403, 422, 429 or 502), plus job_id and status failed. A failed job is not charged.
- 504 job_timeout means the job did not finish in time, and 503 job_interrupted means the service restarted while it ran. Neither is charged. Submit again.
- 404 not_found covers an unknown job_id, a finished answer older than 15 minutes, and a job that belongs to another API key, so a job id cannot be used to probe someone else's jobs.
Related endpoints
- Grok Chat: Submit: Start a Grok chat in the background and get a job id to poll, for clients that time out before a long answer.
- Grok Chat: Ask X's Grok a question and get the answer plus the pages it cited.
- Grok Config: Check whether your account can use Grok, and which models it may pick.
FAQ
How often should I poll?
Wait the poll_after_seconds the last response gave you, which is 3 seconds. The Retry-After header on a 202 carries the same value. Stop on anything other than a 202.
Am I charged again if I poll a finished job twice?
No. Only the first poll that delivers the answer is charged $0.0040, and that charge is claimed atomically, so concurrent polls cannot charge twice. Later polls return the same answer for free until it expires.
What if I never collect the answer?
Then you are not charged. A finished answer is kept for 900 seconds, then deleted, and the charge only happens on delivery. After that, polling returns 404 and you submit again.
How do I tell a failed job from a failed poll?
Read status in the body. A failed job carries job_id and status failed beside the error. A 404 or a 401 with no job_id means the poll itself was refused, and the job's state is unchanged.
Grok Chat: Submit POST
Start the same Grok chat as POST /twitter/grok/chat without holding the connection open. Send the same body and get a 202 with a job_id at once, then poll GET /twitter/grok/chat/result until the answer is ready. Built for clients that time out before a search-grounded answer arrives. A bad body, a missing key, a missing session and a short balance are answered on the spot, before any job exists, and at most 5 jobs per API key can be pending at once. Submitting is free: the $0.0040 grok/chat price is charged once, on the result poll that first delivers a finished answer, and a failed, timed-out, interrupted or never-collected job is not charged. Cost: Free per call.
Grok Config GET
Read the Grok settings for the account behind your session: whether X has enabled Grok for it, the reasons if not, and the model options it is allowed to choose between. Grok eligibility belongs to the X account rather than to us, so this runs as your own session. Call it once before your first chat request. This call is free. Cost: Free per call.