Skip to content

GET & POST

GET and POST are the two methods you will use most. They sit at opposite ends of the safety spectrum: GET only reads, while POST creates and is the least constrained method of all.

A GET retrieves a representation of a resource and must never change server state. Because it is safe, responses can be cached and requests can be freely retried. A GET on a collection returns the list; a GET on an item returns that item or 404.

GET /articles/42 HTTP/1.1
Accept: application/json

A GET should never carry a meaningful request body, and must not have side effects — no “increment view count via GET”, or caches and prefetchers will surprise you.

POST — create and non-idempotent actions

Section titled “POST — create and non-idempotent actions”

A POST submits data to a collection, typically creating a new resource. It is neither safe nor idempotent: sending the same POST twice usually creates two resources. On success, return 201 Created with a Location header pointing to the new resource.

This Hono app exposes a collection you can read and append to. Open it in StackBlitz and try GET /articles, GET /articles/1, and POST /articles:

JavaScript

Using GET to trigger a side effect Symptom:

  • GET /users/\{id\}/activate — activates a user via GET
  • Bots, crawlers, and prefetching trigger the action by accident
  • Any action with a side effect must use POST, PUT, PATCH, or DELETE

Sending sensitive data in a GET query string Symptom:

  • GET /login?password=secret123
  • The password ends up in the URL, server logs, and browser history
  • Use POST with a body for sensitive data

💡 Real-world examples

GitHub API:

  • GET /repos/\{owner\}/\{repo\} — read a repo (safe, idempotent)
  • POST /repos/\{owner\}/\{repo\}/issues — create a new issue (not idempotent)

Stripe API:

  • GET /charges/\{id\} — view a charge (cacheable)
  • POST /charges — create a new charge (needs an idempotency key)

Sources: GitHub REST API — repos, Stripe API — charges

Why must a GET never change server state?
Sending the same POST to a collection twice usually results in what?
What should a successful create return?