TL;DR
REST API URLs should use nouns (resources), not verbs (actions). HTTP methods (GET, POST, PUT, DELETE) are the verbs. Using actions like /getUser or /createOrder in URLs violates REST principles, creates inconsistency, and makes APIs harder to maintain. Modern PetstoreAPI uses resource-oriented URLs throughout.
Introduction
When designing an API endpoint to search for pets by status, you might consider: GET /findPetsByStatus?status=available. While descriptive, this approach is incorrect in REST.
REST APIs should use nouns in URLs, not verbs. The HTTP method represents the action. The correct endpoint: GET /pets?status=available. The URL targets the resource (pets), and the HTTP method specifies the action (get).
The old Swagger Petstore used endpoints like /pet/findByStatus and /pet/findByTags, which violate REST conventions. Modern PetstoreAPI corrects this with resource-oriented URLs.
💡 Tip: If you're building or testing REST APIs, Apidog can help you validate URL design, test endpoints, and enforce REST conventions. Import OpenAPI specs, check for verbs in URLs, and catch design issues early.
This guide covers why verbs don’t belong in REST URLs, how to design resource-oriented endpoints, and how Modern PetstoreAPI implements this correctly.
The Verb Problem in REST APIs
Action verbs in URLs indicate RPC (Remote Procedure Call) thinking, not REST.
RPC-Style URLs (Wrong)
POST /createUser
GET /getUser?id=123
PUT /updateUser
DELETE /deleteUser?id=123
GET /findUsersByRole?role=admin
POST /sendEmail
GET /calculateTotal
These are function calls, not REST endpoints.
REST-Style URLs (Correct)
POST /users
GET /users/123
PUT /users/123
DELETE /users/123
GET /users?role=admin
POST /emails
GET /orders/123/total
URLs represent resources; HTTP methods specify actions.
Why This Matters
Consistency: REST URLs follow predictable patterns based on resources:
-
GET /pets– List pets -
POST /pets– Create pet -
GET /pets/{id}– Get pet -
PUT /pets/{id}– Update pet -
DELETE /pets/{id}– Delete pet
Verb-based URLs are inconsistent and unpredictable.
Scalability: Verb-based URLs multiply as features grow:
/findPetsByStatus/findPetsByTags/findPetsByOwner/findPetsByBreed/searchPets/queryPets
With resource-oriented URLs, a single endpoint handles filtering:
GET /pets?status=availableGET /pets?tags=friendlyGET /pets?owner=johnGET /pets?breed=labrador
Why HTTP Methods Are the Verbs
REST leverages HTTP’s built-in verbs so you don’t need to invent your own.
HTTP Methods Map to CRUD
POST → Create
GET → Read
PUT → Update (replace)
PATCH → Update (partial)
DELETE → Delete
-
GETis safe and idempotent. -
POSTcreates resources. -
DELETEremoves them.
Example: User Management
Wrong (verbs in URLs):
POST /createUser
GET /getUser?id=123
POST /updateUser
POST /deleteUser
Correct (HTTP methods as verbs):
POST /users # Create user
GET /users/123 # Get user
PUT /users/123 # Update user
DELETE /users/123 # Delete user
The resource stays the same; only the method changes.
Benefits of Using HTTP Methods
-
Caching:
GETrequests can be cached. UsingPOST /getUserprevents proper caching. -
Idempotency:
PUTandDELETEare idempotent, supporting safe retries. -
Safety:
GETdoes not modify state; it’s safe for crawlers/tools. - Standards Compliance: HTTP clients, proxies, and caches understand standard methods, not custom verbs.
Real Examples from Swagger Petstore
Example 1: Finding Pets by Status
Swagger Petstore (Wrong):
GET /pet/findByStatus?status=available
Problems:
-
findByStatusis a verb phrase - Inconsistent with
/pet/{id} - Hard to extend (e.g., other search criteria)
Modern PetstoreAPI (Correct):
GET /pets?status=AVAILABLE
Benefits:
- Resource-oriented (
/pets) - Uses query parameters for filtering
- Consistent and easy to extend:
GET /pets?status=AVAILABLE&species=dog
See the Modern PetstoreAPI REST documentation for detailed implementation.
Example 2: Finding Pets by Tags
Swagger Petstore (Wrong):
GET /pet/findByTags?tags=tag1,tag2
Modern PetstoreAPI (Correct):
GET /pets?tags=friendly,trained
Example 3: User Login
Swagger Petstore (Wrong):
GET /user/login?username=john&password=secret
Problems:
-
loginis a verb - Using
GETfor authentication (security risk) - Passwords in URL parameters
Modern PetstoreAPI (Correct):
POST /auth/login
Content-Type: application/json
{
"username": "john",
"password": "secret123"
}
Benefits:
- Resource-oriented (
/auth) - Uses
POST - Credentials in request body
- Returns JWT token
How Modern PetstoreAPI Fixes This
Modern PetstoreAPI uses resource-oriented URLs for all endpoints.
Pet Management
GET /pets # List all pets
GET /pets?status=AVAILABLE # Filter by status
GET /pets?species=dog # Filter by species
GET /pets/{id} # Get specific pet
POST /pets # Create new pet
PUT /pets/{id} # Update pet
PATCH /pets/{id} # Partial update
DELETE /pets/{id} # Delete pet
No verbs in URLs—just resources.
Order Management
GET /orders # List orders
GET /orders/{id} # Get order
POST /orders # Create order
PUT /orders/{id} # Update order
DELETE /orders/{id} # Cancel order
GET /orders/{id}/items # Get order items
Complex Operations
For operations beyond standard CRUD, use sub-resources:
POST /orders/{id}/payment # Process payment for order
POST /orders/{id}/shipment # Create shipment for order
POST /pets/{id}/adoption # Start adoption process
These sub-resources still follow resource-oriented patterns.
When Verbs Seem Necessary
Some operations don’t fit CRUD exactly. Here’s how to keep URLs resource-oriented.
Search Operations
Wrong:
GET /searchPets?query=labrador
Correct (Option 1):
GET /pets?search=labrador
Correct (Option 2):
GET /pets/search?q=labrador
Correct (Option 3):
QUERY /pets
Content-Type: application/json
{
"query": "labrador",
"filters": {
"status": "AVAILABLE"
}
}
Modern PetstoreAPI supports all three depending on complexity.
Calculations
Wrong:
GET /calculateShipping?weight=10&destination=NY
Correct:
GET /shipping-estimates?weight=10&destination=NY
Use resources (shipping-estimates), not actions.
Batch Operations
Wrong:
POST /batchDeletePets
Correct:
DELETE /pets?ids=1,2,3
Or, use a batch resource:
POST /pets/batch-operations
Content-Type: application/json
{
"operation": "delete",
"ids": [1, 2, 3]
}
Actions That Change State
Wrong:
POST /activateUser
POST /deactivateUser
Correct:
PATCH /users/{id}
Content-Type: application/json
{
"status": "ACTIVE"
}
State changes should be modeled as resource updates.
Testing URL Design with Apidog
Apidog helps validate REST API design and identify verbs in URLs.
Import Modern PetstoreAPI
- Import the Modern PetstoreAPI OpenAPI spec
- Apidog generates test cases automatically
- Review endpoint structure and naming
Check for Verbs in URLs
Create a custom validation rule in Apidog:
// Check if URL contains common action verbs
const verbs = ['get', 'create', 'update', 'delete', 'find', 'search',
'calculate', 'process', 'send', 'fetch'];
const url = request.url.toLowerCase();
for (const verb of verbs) {
if (url.includes(`/${verb}`)) {
throw new Error(`URL contains verb: ${verb}. Use resource-oriented URLs instead.`);
}
}
Test Endpoint Consistency
Apidog can verify endpoint patterns:
✓ GET /pets
✓ POST /pets
✓ GET /pets/{id}
✓ PUT /pets/{id}
✓ DELETE /pets/{id}
All share the /pets resource.
Compare Against Modern PetstoreAPI
- Import your API and Modern PetstoreAPI into Apidog
- Compare endpoint structures side-by-side
- Identify inconsistencies or verb usage
- Refactor your API to match REST conventions
Migration Strategies
If your API uses verbs in URLs, use these migration steps.
Strategy 1: Versioning
Release a new version with correct URLs:
# Old API (v1)
GET /api/v1/findPetsByStatus?status=available
# New API (v2)
GET /api/v2/pets?status=available
Maintain v1, but encourage migration to v2.
Strategy 2: Aliasing
Support old and new URLs temporarily:
# Old URL (deprecated)
GET /pet/findByStatus?status=available
# New URL (preferred)
GET /pets?status=available
Return a deprecation warning:
{
"data": [...],
"warnings": [
{
"code": "DEPRECATED_ENDPOINT",
"message": "This endpoint is deprecated. Use GET /pets?status=available instead.",
"sunset": "2027-01-01"
}
]
}
Strategy 3: Redirects
Use HTTP 301 redirects for simple cases:
GET /pet/findByStatus?status=available
→ 301 Moved Permanently
Location: /pets?status=available
Works for GET requests, not for POST, PUT, or DELETE.
Conclusion
REST API URLs should use nouns (resources); HTTP methods provide the verbs. This ensures consistency, scalability, and maintainability.
The old Swagger Petstore used endpoints like /pet/findByStatus. Modern PetstoreAPI corrects this with resource-oriented URLs, such as /pets?status=AVAILABLE.
Key takeaways:
- Use nouns in URLs:
/pets,/orders,/users - Let HTTP methods be the verbs:
GET,POST,PUT,DELETE - Use query parameters for filtering:
/pets?status=available - For complex operations, use sub-resources:
/orders/{id}/payment - Test your API design with Apidog to catch verb usage early
Review the Modern PetstoreAPI documentation for more examples.
FAQ
Can I ever use verbs in REST URLs?
Rarely. If an operation doesn’t fit the resource model (e.g., /search or /login), a verb might be justified. In most cases, model it as a resource.
What about /login and /logout?
These are common exceptions. Many APIs use /auth/login and /auth/logout. Alternatively, use resources: POST /sessions (login) and DELETE /sessions/{id} (logout).
How do I handle complex queries?
Use query parameters for simple filters: /pets?status=available&species=dog. For complex queries, use the QUERY HTTP method or a search resource: POST /pets/search.
What if my operation doesn’t map to CRUD?
Model it as a sub-resource. Instead of POST /processPayment, use POST /orders/{id}/payment.
How do I test if my URLs are resource-oriented?
Use Apidog to import your OpenAPI spec and check for verbs in URLs. Compare against Modern PetstoreAPI as a reference.
Should I use /pets/search or /pets?search=query?
Both are valid. /pets?search=query is simpler for basic search. /pets/search or QUERY /pets is better for complex queries.
How do I migrate from verb-based URLs?
Use API versioning (e.g., /v2/pets), add deprecation warnings, and give clients time to migrate. See the Migration Strategies section above.
Does Modern PetstoreAPI use any verbs in URLs?
Modern PetstoreAPI avoids verbs in URLs. Operations like search, filter, and authentication are modeled as resources or use query parameters. Review the REST API documentation for examples.
Top comments (0)