HTTP 202 Accepted

Accepted

HTTP 202 is Accepted: the server has taken the request for processing but hasn’t finished, and the work may still fail or never happen (RFC 9110 section 15.3.3). RFC 9110 calls it intentionally noncommittal. HTTP has no way to deliver the real outcome later, so the response ought to describe the request’s current status and point to, or embed, a status monitor the client can check.

The pattern

POST /exports HTTP/1.1
Content-Type: application/json

{"format": "csv", "month": "2026-09"}

HTTP/1.1 202 Accepted
Location: /exports/jobs/7f3a
Retry-After: 5
Content-Type: application/json

{"id": "7f3a", "status": "queued"}

The client polls the monitor until the job ends:

GET /exports/jobs/7f3a HTTP/1.1

HTTP/1.1 200 OK
Content-Type: application/json

{"id": "7f3a", "status": "done", "result": "/exports/7f3a.csv"}

RFC 9110 defines what Location means on a 201 or a 3xx, not on a 202, so pointing it at the monitor is a convention, as is Retry-After for the polling interval. Azure Resource Manager’s long-running operations work this way. Say in the body where the monitor is too, and report failures there as a status, since the monitor itself answered fine.

202, 201 or 200

the work is done and created something       201 Created, Location names it
the work is done                             200 OK or 204 No Content
the work is queued or still running          202 Accepted

Don’t send 202 for work you finished synchronously, and don’t send 201 for a resource that won’t exist until a job runs.

Who sends it

  • GitHub’s repository statistics endpoints answer 202 while they compute the numbers; GitHub asks clients to wait a moment and request again.
  • AWS Lambda answers an asynchronous invocation (InvocationType=Event) with 202: the event is queued, not run.
  • Webhook receivers often answer 202 at once and process the event in the background, so the sender doesn’t time out.

Gotchas

  • 202 isn’t heuristically cacheable. Mark the monitor Cache-Control: no-store so no cache hands back an old queued.
  • A client that times out and resends the POST can queue the job twice. Deduplicate retried submissions, for example with a client-supplied idempotency key.
app.post('/exports', async (req, res) => {                     // Express
  const job = await queue.add('export', req.body);
  res.status(202).location(`/exports/jobs/${job.id}`).set('Retry-After', '5').json({ id: job.id, status: 'queued' });
});
@app.post("/exports", status_code=202)                         # FastAPI
async def create_export(req: ExportRequest):
    job = await queue.enqueue(req)
    return {"id": job.id, "status": "queued"}
w.Header().Set("Location", "/exports/jobs/"+job.ID)
w.WriteHeader(http.StatusAccepted)

Search 201 202 in the tool below to compare the two.

Try it in the HTTP Status Codes

202 Accepted

  1. 202Accepted2xx Success

    The request has been accepted for processing but is not finished, and there is no promise that it ever will be. The body usually carries a ticket the client can poll.

    When to use it

    Queues and background work: the request is recorded, the answer comes later.

    Common mistakes

    Returning it when the work is already done, and accepting a job with no way for the client to learn how it went.

    Not cacheable by defaultRFC 9110

Every code, by class

Codes marked unofficial come from one server’s own convention — nginx, Cloudflare, cPanel, Microsoft — and are not in the IANA registry.

Runs in your browser. Nothing you enter is sent anywhere.