Idempotent describes an operation whose intended effect on the server is the same whether it runs once or many times, which is what makes it safe to retry after a timeout. In HTTP, RFC 9110 section 9.2.2 defines it for request methods: PUT, DELETE and all safe methods are idempotent, while POST is not.
The word comes from mathematics, where a function is idempotent if applying it twice gives the same result as applying it once. In an API the test is about server state, not about the response you receive.
The rule exists because of retries. If a connection drops before the response arrives, the client cannot know whether the server acted. For idempotent methods the client may safely send the request again. A client should not automatically retry a non-idempotent request, and a proxy must not.
For POST, APIs commonly add an idempotency key: a unique value the client sends and the server remembers. The transcript below shows a server that does exactly that, compared with plain PUT, DELETE and POST.
PUT, 1st PUT /orders/a1 201 {"id":"a1"}
PUT, 2nd (same) PUT /orders/a1 200 {"id":"a1"}
DELETE, 1st DELETE /orders/a1 204 (empty)
DELETE, 2nd DELETE /orders/a1 404 {"error":"not found"}
POST, 1st POST /orders 201 {"id":"o1"}
POST, retry POST /orders 201 {"id":"o2"}
POST + key, 1st POST /orders 201 {"id":"o3"}
POST + key, retry POST /orders 201 {"id":"o3"}
orders stored: o1,o2,o3
The plain POST retry created a second order, o2. The keyed retry returned the stored result for o3 and created nothing new.
No, POST is not idempotent in the HTTP specification, and sending the same POST twice can create two records. A client should only retry it automatically when it knows the request is safe for that resource, or can detect that the first attempt never took effect. An idempotency key lets a server make a specific POST endpoint behave idempotently.
A safe method asks for no state change at all, while an idempotent method may change state but only once. Every safe method is idempotent, but PUT and DELETE are idempotent without being safe. GET, HEAD, OPTIONS and TRACE are the safe ones.
PUT /counter handler that does count += 1 is not idempotent, and retries will corrupt it. PUT must replace state with what the body says.