TL;DR
REST API resource names should be plural. Use /pets/{id} not /pet/{id}. Plural names represent collections consistently, align with HTTP semantics, and match how developers think about resources. Modern PetstoreAPI uses plural names throughout its API design, following industry best practices.
Introduction
You’re designing a REST API. You need an endpoint to get a user by ID. Do you use /user/123 or /users/123? This question has sparked countless debates, Stack Overflow threads, and team arguments.
The answer is clear: use plural. But understanding why matters more than memorizing the rule. The reasoning connects to how REST works, how collections behave, and how developers think about resources.
The old Swagger Petstore got this wrong, using /pet/{id} instead of /pets/{id}. This inconsistency taught millions of developers the wrong pattern. Modern PetstoreAPI fixes this by using plural names consistently across all endpoints.
In this guide, you’ll learn why plural names are the right choice, how they align with REST principles, and how to implement them correctly using Modern PetstoreAPI as a reference.
The Plural vs Singular Debate
The debate exists because both approaches seem logical at first glance.
The Singular Argument
“When I request /user/123, I’m getting one user, not multiple users. Singular makes sense.”
This reasoning focuses on the response—you’re getting a single resource, so the URL should be singular.
The Plural Argument
“The URL represents a collection. /users is the collection of all users. /users/123 is item 123 in that collection.”
This reasoning focuses on the resource structure—URLs represent collections, and you’re accessing items within those collections.
Why This Matters
Your choice affects:
- API consistency - Mixed naming confuses developers
- Mental models - How developers understand your API structure
- Code generation - Tools generate client code based on resource names
- Documentation clarity - Docs need to explain your naming logic
Why Plural Names Win
Plural resource names align with REST principles and HTTP semantics. Here’s why.
1. Collections Are Plural
In REST, resources are collections. When you access /users, you’re accessing the users collection. When you access /users/123, you’re accessing item 123 in the users collection.
GET /users ← The users collection
GET /users/123 ← Item 123 in the users collection
POST /users ← Add to the users collection
DELETE /users/123 ← Remove item 123 from the users collection
This mental model is consistent. The collection is always /users, whether you’re accessing all items or one item.
With singular names, the mental model breaks:
GET /user ← Which user?
GET /user/123 ← This makes sense
POST /user ← Add to... what?
2. HTTP Methods Operate on Collections
HTTP methods describe operations on collections:
GET /users- Retrieve the collectionPOST /users- Add to the collectionGET /users/123- Retrieve item 123 from the collectionPUT /users/123- Replace item 123 in the collectionDELETE /users/123- Remove item 123 from the collection
The collection is the resource. Individual items are members of that collection.
3. Consistency Across Endpoints
Plural names create consistency:
GET /pets ← Collection
GET /pets/123 ← Item in collection
GET /orders ← Collection
GET /orders/456 ← Item in collection
Singular names force you to switch between singular and plural:
GET /pet ← Doesn't make sense
GET /pet/123 ← Makes sense
GET /pets ← Wait, now it's plural?
4. Industry Standards
Major APIs use plural names:
- GitHub API:
/repos,/users,/issues - Stripe API:
/customers,/charges,/subscriptions - Twilio API:
/accounts,/messages,/calls - Google APIs:
/users,/groups,/files
Modern PetstoreAPI follows this standard with /pets, /orders, /users.
The Collection Mental Model
Understanding collections helps you design better APIs.
Collections in REST
A collection is a set of resources. In a pet store API:
/pets- The collection of all pets/orders- The collection of all orders/users- The collection of all users
Each collection supports operations:
GET /pets ← List pets (with filtering, pagination)
POST /pets ← Create a new pet
GET /pets/{id} ← Get a specific pet
PUT /pets/{id} ← Update a specific pet
DELETE /pets/{id} ← Delete a specific pet
Sub-Collections
Collections can contain sub-collections:
GET /pets/{id}/photos ← Photos collection for pet {id}
POST /pets/{id}/photos ← Add photo to pet {id}
GET /pets/{id}/photos/{photoId} ← Specific photo
The pattern stays consistent: collections are plural, items are accessed by ID.
Modern PetstoreAPI Example
Modern PetstoreAPI implements this correctly:
GET /pets
GET /pets/{petId}
GET /pets/{petId}/photos
POST /pets/{petId}/vaccinations
GET /orders
GET /orders/{orderId}
GET /orders/{orderId}/items
Every collection is plural. Every item access uses {id} within that collection.
How Modern PetstoreAPI Uses Plural Names
Let’s see real examples from Modern PetstoreAPI.
Pet Resources
GET /pets ← List all pets
POST /pets ← Create a new pet
GET /pets/{petId} ← Get specific pet
PUT /pets/{petId} ← Update pet
DELETE /pets/{petId} ← Delete pet
GET /pets?status=AVAILABLE ← Filter pets by status
Order Resources
GET /orders ← List all orders
POST /orders ← Create order
GET /orders/{orderId} ← Get specific order
PUT /orders/{orderId} ← Update order
DELETE /orders/{orderId} ← Cancel order
User Resources
GET /users ← List users
POST /users ← Create user
GET /users/{userId} ← Get specific user
PUT /users/{userId} ← Update user
DELETE /users/{userId} ← Delete user
Nested Resources
GET /pets/{petId}/photos ← Pet's photos
POST /pets/{petId}/photos ← Add photo
GET /pets/{petId}/vaccinations ← Pet's vaccinations
POST /pets/{petId}/vaccinations ← Record vaccination
GET /orders/{orderId}/items ← Order items
Check the full REST API documentation for complete endpoint listings.
Common Arguments for Singular (and Why They’re Wrong)
Let’s address common arguments for singular names.
Argument 1: “The Response Is Singular”
Claim: “When I GET /user/123, I get one user. Singular makes sense.”
Counter: The URL represents the resource location, not the response. /users/123 means “item 123 in the users collection.” The response being singular doesn’t change the collection structure.
Argument 2: “It Reads Better in Code”
Claim: “getUser(id) reads better than getUsers(id).”
Counter: Your client code naming is independent of URL structure. You can have:
// URL: GET /users/123
function getUser(id) {
return api.get(`/users/${id}`);
}
The function name doesn’t need to match the URL.
Argument 3: “Singular Avoids Grammar Issues”
Claim: “What about resources like ‘status’ or ‘information’ that don’t have clear plurals?”
Counter: These are usually singleton resources, not collections. Use singular for singletons:
GET /status ← System status (singleton)
GET /configuration ← App config (singleton)
GET /users ← Users collection (plural)
Argument 4: “My ORM Uses Singular Table Names”
Claim: “My database tables are singular (user, order), so my API should match.”
Counter: Your API design shouldn’t leak database implementation details. REST APIs represent resources, not database tables. Use plural for collections regardless of your database schema.
Testing Resource Naming with Apidog
Apidog helps you validate and test resource naming conventions.
Import Modern PetstoreAPI
- Import the Modern PetstoreAPI OpenAPI spec
- Apidog automatically detects resource patterns
- Review endpoint naming for consistency
Create Naming Convention Tests
// Apidog test script
pm.test("Resource names are plural", function() {
const path = pm.request.url.getPath();
const segments = path.split('/').filter(s => s);
// Check first segment is plural
const resource = segments[0];
pm.expect(resource).to.match(/s$/); // Ends with 's'
});
Validate Consistency
Apidog can check:
- All collection endpoints use plural names
- Sub-resources follow the same pattern
- No mixing of singular/plural in the same API
Test with Real Requests
GET https://api.petstoreapi.com/v1/pets
GET https://api.petstoreapi.com/v1/pets/019b4132-70aa-764f-b315-e2803d882a24
GET https://api.petstoreapi.com/v1/orders
Apidog validates responses and helps you ensure naming consistency across your API.
Edge Cases and Exceptions
Some resources don’t fit the plural pattern.
Singleton Resources
Resources that exist only once should be singular:
GET /status ← System status
GET /configuration ← App configuration
GET /health ← Health check
GET /metrics ← System metrics
These aren’t collections, so plural doesn’t apply.
Controller Resources
Actions that don’t fit CRUD operations:
POST /login ← Authentication action
POST /logout ← Session termination
POST /search ← Complex search operation
These are acceptable exceptions because they represent actions, not resources.
Uncountable Nouns
Some nouns don’t have clear plurals:
GET /information ← Singular (uncountable)
GET /data ← Singular (uncountable)
GET /equipment ← Singular (uncountable)
Use singular for uncountable nouns, but these are rare in typical APIs.
Modern PetstoreAPI Approach
Modern PetstoreAPI handles these cases:
# Collections (plural)
GET /pets
GET /orders
GET /users
# Singletons (singular)
GET /health
GET /metrics
# Actions (singular verbs)
POST /login
POST /logout
Conclusion
REST API resource names should be plural. This aligns with collection semantics, HTTP methods, and industry standards. Modern PetstoreAPI demonstrates this pattern correctly across all endpoints.
Key takeaways:
- Use plural names for collections (
/pets,/orders,/users) - Individual items are accessed within collections (
/pets/123) - Singleton resources can be singular (
/status,/health) - Consistency matters more than perfection
- Test your naming conventions with Apidog
The plural vs singular debate is settled. Follow the industry standard, use plural names, and build APIs that developers understand intuitively.
Next steps:
- Review your API endpoints for naming consistency
- Check Modern PetstoreAPI documentation for reference patterns
- Use Apidog to validate your API design
- Update your OpenAPI spec with plural resource names
FAQ
Should I change my existing API from singular to plural?
If your API is already in production, changing resource names is a breaking change. Consider:
- Adding new v2 endpoints with plural names
- Maintaining backward compatibility with redirects
- Documenting the naming convention clearly
Don’t break existing clients for naming consistency alone.
What about resources that are already plural?
If the resource name is naturally plural (like “analytics” or “series”), keep it as-is:
GET /analytics ← Already plural
GET /series ← Already plural
GET /species ← Already plural
How do I handle nested resources?
Keep both levels plural:
GET /users/{userId}/orders ← Both plural
GET /pets/{petId}/vaccinations ← Both plural
GET /orders/{orderId}/items ← Both plural
What if my team prefers singular?
Consistency within your API matters most. If your team has already standardized on singular names and changing would cause confusion, stick with singular. But for new APIs, use plural.
Does GraphQL use plural or singular?
GraphQL typically uses singular for single-item queries and plural for lists:
query {
user(id: "123") { ... } # Singular
users(limit: 10) { ... } # Plural
}
This is different from REST because GraphQL queries are explicit about returning one vs many.
How does Modern PetstoreAPI handle this?
Modern PetstoreAPI uses plural names consistently across all REST endpoints. Check the REST API guide for complete examples.
Can I test naming conventions automatically?
Yes, Apidog can run automated tests to check resource naming patterns across your entire API. Import your OpenAPI spec and create test cases for naming conventions.
What about non-English APIs?
The plural rule applies regardless of language. If your API uses French resource names, use French plurals. If it uses Japanese, follow Japanese grammar rules. The principle (collections are plural) remains the same.



