REST CRUD Explained: Create, Read, Update, Delete Walkthrough
CRUD is the heartbeat of REST. Create, Read, Update, Delete — walked through end to end.
The four verbs, one after another
CRUD stands for Create, Read, Update, Delete — the four operations every data-driven application performs. In REST, each maps to an HTTP method:
| Operation | Method | URL | Body | Success status |
|---|---|---|---|---|
| Create | POST | /users | full user | 201 Created |
| Read (list) | GET | /users | none | 200 OK |
| Read (one) | GET | /users/{id} | none | 200 OK (or 404) |
| Update (partial) | PATCH | /users/{id} | changed fields | 200 OK |
| Update (full) | PUT | /users/{id} | full user | 200 OK |
| Delete | DELETE | /users/{id} | none | 204 No Content |
Let's walk through the full cycle.
Step 1 — Create
/api/v1/userscurl -X POST 'https://demo.totalshiftleft.ai/api/v1/users' \
-H 'Content-Type: application/json' \
-d '{"name":"Alice","email":"alice@example.com","role":"user"}'Things to notice:
- Status is 201 Created, not 200.
- The response echoes the created resource, including a server-generated
id(UUID) andcreated_attimestamp. - Copy the
idfrom the response — you'll need it for steps 3 and 4.
Step 2 — Read
/api/v1/userscurl -X GET 'https://demo.totalshiftleft.ai/api/v1/users'This lists all users in your sandbox session. The user you created in step 1 is there. Single-resource reads use GET /users/{id} — try changing the path to read just your user by ID.
A detail that catches people out: an empty list [] from a search or filter is success. Only return 404 when the specific resource at that URL genuinely doesn't exist. GET /users?role=banana matching nothing should return 200 [] with pagination metadata.
Step 3 — Update (PATCH)
Replace {id} in the widget below with the UUID from step 1, then click Run:
/api/v1/users/{id}curl -X PATCH 'https://demo.totalshiftleft.ai/api/v1/users/{id}' \
-H 'Content-Type: application/json' \
-d '{"role":"admin"}'You sent only { "role": "admin" }. The response shows the full user — but only the role changed. Name, email, and other fields are preserved. That's PATCH.
If you used PUT, you'd need to send the complete user object. Miss the email? It might be blanked out or the request might 400 depending on the API.
Step 4 — Delete
Again, replace {id}:
/api/v1/users/{id}curl -X DELETE 'https://demo.totalshiftleft.ai/api/v1/users/{id}'- Status is 204 No Content. No response body.
- If you try to GET the same user ID now, you'll get 404.
- If you try to DELETE the same user again, most well-designed APIs return 404 or 204 (both are defensible — DELETE is idempotent, so "already gone" and "just deleted" are the same outcome).
What a full CRUD test suite should cover
For every resource in your API, a thorough test suite covers:
- Happy paths — one successful call per method.
- Not found — GET/PATCH/PUT/DELETE on a non-existent ID returns 404.
- Validation errors — POST/PATCH/PUT with invalid body returns 400 with field-level details.
- Duplicates — POST with duplicate unique fields (email) returns 409.
- Auth — every write method requires authentication; assert 401 without a token.
- Authorization — a non-admin trying to create an admin returns 403.
For a single resource type, that's ~20 test cases. Multiply by every resource in your API. This is exactly where test-generation from OpenAPI saves most of the work.
Common CRUD bugs
1. PATCH that silently ignores unknown fields. If you PATCH { "roel": "admin" } (typo), a lot of APIs just ignore it. The user expects their role to change; it doesn't. Harder to catch than an explicit error. Well-designed APIs 400 on unknown fields.
2. Update returning stale data. Some APIs cache the resource and return the pre-update state after a successful PATCH. The write succeeded, but the response shows the old data. Test explicitly that the fields you changed are reflected in the response.
3. DELETE that doesn't actually delete. Soft deletes (setting deleted_at instead of actually removing rows) are fine — but the behavior must be consistent. GET /users/123 after DELETE should return 404, even if the row still exists in the database with a tombstone flag.
What's next
You've done the CRUD cycle. Next lesson: PATCH vs PUT — the difference that trips everyone up — a deep dive on the single most confused pair of HTTP methods.
Related lessons
REST is the default API style on the web. Here's what it actually means — stripped of jargon and with runnable examples.
PUT replaces. PATCH modifies. Here's the subtle but critical difference — and why it matters for testing.
Fifteen conventions that make REST APIs a joy to use — and the absence of any one is a smell.