DEV Community

Cover image for Should REST API Resource Names Be Plural or Singular?
Wanda
Wanda

Posted on • Originally published at apidog.com

Should REST API Resource Names Be Plural or Singular?

TL;DR

REST API resource names should be plural. Use /pets/{id} not /pet/{id}. Plural names consistently represent collections, align with HTTP semantics, and match how developers think about resources. Modern PetstoreAPI uses plural names throughout its API, following industry best practices.

Try Apidog today

Introduction

When designing a REST API, you’ll face the question: should your endpoint be /user/123 or /users/123? This is a common debate among developers.

The answer: use plural. But understanding the reasoning is crucial. Plural resource names fit REST’s collection model, HTTP semantics, and developer expectations.

The old Swagger Petstore used /pet/{id}—an inconsistency that spread the wrong convention. Modern PetstoreAPI fixes this by consistently using plural resource names.

💡 Tip: If you’re building or testing REST APIs, Apidog helps you validate resource naming, test endpoint consistency, and ensure your API follows REST best practices. Import OpenAPI specs, check naming patterns, and catch inconsistencies before release.

This guide explains why plural names are the right choice, how they fit REST principles, and how to implement them—using Modern PetstoreAPI as a reference.

The Plural vs Singular Debate

Both singular and plural seem reasonable at first glance.

The Singular Argument

“When I request /user/123, I’m getting one user. Singular feels right.”

This reasoning focuses on the response—a single resource, so a singular path.

The Plural Argument

“The URL represents a collection. /users is the collection. /users/123 is an item in that collection.”

This focuses on the resource structure—URLs represent collections, and you access items within them.

Why This Matters

Your choice impacts:

  • API consistency – Mixed naming confuses developers.
  • Mental models – Influences how developers understand your API.
  • Code generation – Tools generate code based on resource names.
  • Documentation clarity – Docs must explain your structure.

Why Plural Names Win

Plural resource names align with REST and HTTP semantics. Here’s how:

1. Collections Are Plural

Resources are collections. For example:

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
Enter fullscreen mode Exit fullscreen mode

This is a consistent mental model. With singular names, the logic breaks:

GET /user           ← Which user?
GET /user/123       ← Makes sense
POST /user          ← Add to... what?
Enter fullscreen mode Exit fullscreen mode

2. HTTP Methods Operate on Collections

HTTP verbs operate on collections:

  • GET /users – Retrieve the collection
  • POST /users – Add to the collection
  • GET /users/123 – Retrieve an item from the collection
  • PUT /users/123 – Replace an item
  • DELETE /users/123 – Remove an item

3. Consistency Across Endpoints

Plural naming keeps endpoints consistent:

GET /pets           ← Collection
GET /pets/123       ← Item in collection
GET /orders         ← Collection
GET /orders/456     ← Item in collection
Enter fullscreen mode Exit fullscreen mode

With singular, you risk inconsistency:

GET /pet            ← Doesn't make sense
GET /pet/123        ← OK
GET /pets           ← Now it's plural?
Enter fullscreen mode Exit fullscreen mode

4. Industry Standards

Major APIs use plurals:

  • GitHub: /repos, /users, /issues
  • Stripe: /customers, /charges, /subscriptions
  • Twilio: /accounts, /messages, /calls
  • Google: /users, /groups, /files

Modern PetstoreAPI follows this with /pets, /orders, /users.

The Collection Mental Model

Understanding collections improves API design.

Collections in REST

A collection is a set of resources. For a pet store API:

  • /pets – All pets
  • /orders – All orders
  • /users – All users

Standard operations:

GET /pets           ← List pets (filter, paginate)
POST /pets          ← Create a pet
GET /pets/{id}      ← Get a pet
PUT /pets/{id}      ← Update a pet
DELETE /pets/{id}   ← Delete a pet
Enter fullscreen mode Exit fullscreen mode

Sub-Collections

Collections can have sub-collections:

GET /pets/{id}/photos           ← Photos for pet {id}
POST /pets/{id}/photos          ← Add photo to pet {id}
GET /pets/{id}/photos/{photoId} ← Specific photo
Enter fullscreen mode Exit fullscreen mode

Pattern: collections are plural, items accessed by ID.

Modern PetstoreAPI Example

Modern PetstoreAPI docs implement this:

GET /pets
GET /pets/{petId}
GET /pets/{petId}/photos
POST /pets/{petId}/vaccinations
GET /orders
GET /orders/{orderId}
GET /orders/{orderId}/items
Enter fullscreen mode Exit fullscreen mode

Every collection is plural. Items are accessed by {id} within that collection.

How Modern PetstoreAPI Uses Plural Names

Real API examples from Modern PetstoreAPI:

Pet Resources

GET    /pets                    ← List all pets
POST   /pets                    ← Create a new pet
GET    /pets/{petId}            ← Get a specific pet
PUT    /pets/{petId}            ← Update a pet
DELETE /pets/{petId}            ← Delete a pet
GET    /pets?status=AVAILABLE   ← Filter pets by status
Enter fullscreen mode Exit fullscreen mode

Order Resources

GET    /orders                  ← List all orders
POST   /orders                  ← Create order
GET    /orders/{orderId}        ← Get a specific order
PUT    /orders/{orderId}        ← Update order
DELETE /orders/{orderId}        ← Cancel order
Enter fullscreen mode Exit fullscreen mode

User Resources

GET    /users                   ← List users
POST   /users                   ← Create user
GET    /users/{userId}          ← Get a specific user
PUT    /users/{userId}          ← Update user
DELETE /users/{userId}          ← Delete user
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

See the full REST API documentation for all endpoints.

Common Arguments for Singular (and Why They’re Wrong)

Let’s address common singular arguments.

Argument 1: “The Response Is Singular”

Claim: “When I GET /user/123, I get one user. Singular makes sense.”

Counter: The URL is about resource location, not response count. /users/123 means “item 123 in the users collection”—the response being singular doesn’t matter.

Argument 2: “It Reads Better in Code”

Claim: "getUser(id) is better than getUsers(id)."

Counter: Client code naming is independent from URL structure:

// URL: GET /users/123
function getUser(id) {
  return api.get(`/users/${id}`);
}
Enter fullscreen mode Exit fullscreen mode

Use singular names in code, plural in URLs.

Argument 3: “Singular Avoids Grammar Issues”

Claim: “‘Status’ or ‘information’ have no plurals.”

Counter: These are singleton resources, not collections. Use singular for singletons:

GET /status         ← System status
GET /configuration  ← App config
GET /users          ← Users collection (plural)
Enter fullscreen mode Exit fullscreen mode

Argument 4: “My ORM Uses Singular Table Names”

Claim: “My DB tables are singular (user), so my API should match.”

Counter: API design is not tied to your database schema. REST APIs represent resources, not tables. Collections are always plural at the API level.

Testing Resource Naming with Apidog

Apidog helps validate and test resource naming conventions.

Import Modern PetstoreAPI

  1. Import the Modern PetstoreAPI OpenAPI spec.
  2. Apidog auto-detects resource patterns.
  3. 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'
});
Enter fullscreen mode Exit fullscreen mode

Validate Consistency

Apidog can check:

  • All collections 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
Enter fullscreen mode Exit fullscreen mode

Apidog validates responses and ensures naming consistency across your API.

Edge Cases and Exceptions

Some resources don’t fit the plural pattern.

Singleton Resources

Use singular for resources that exist only once:

GET /status         ← System status
GET /configuration  ← App configuration
GET /health         ← Health check
GET /metrics        ← System metrics
Enter fullscreen mode Exit fullscreen mode

Controller Resources

Actions, not collections:

POST /login         ← Authentication action
POST /logout        ← Session termination
POST /search        ← Complex search
Enter fullscreen mode Exit fullscreen mode

Uncountable Nouns

Use singular for uncountable nouns:

GET /information
GET /data
GET /equipment
Enter fullscreen mode Exit fullscreen mode

These are rare in typical APIs.

Modern PetstoreAPI Approach

Modern PetstoreAPI handles cases as follows:

# Collections (plural)
GET /pets
GET /orders
GET /users

# Singletons (singular)
GET /health
GET /metrics

# Actions (singular verbs)
POST /login
POST /logout
Enter fullscreen mode Exit fullscreen mode

Conclusion

REST API resource names should be plural. This matches collection semantics, HTTP methods, and industry standards. Modern PetstoreAPI demonstrates this pattern consistently.

Key takeaways:

  • Use plural names for collections (/pets, /orders, /users)
  • Access individual items within collections (/pets/123)
  • Singleton resources can be singular (/status, /health)
  • Prioritize consistency
  • Test naming conventions with Apidog

The debate is settled. Use plural names for intuitive, maintainable APIs.

Next steps:

  1. Review your API endpoints for naming consistency
  2. Check Modern PetstoreAPI documentation for samples
  3. Use Apidog to validate your API design
  4. Update your OpenAPI spec with plural resource names

FAQ

Should I change my existing API from singular to plural?

If your API is in production, changing resource names is breaking. Instead:

  • Add new v2 endpoints with plural names
  • Maintain backward compatibility
  • Document the naming convention clearly

Don’t break clients just for naming consistency.

What about resources that are already plural?

If the name is naturally plural (e.g., “analytics”, “series”), keep it as-is:

GET /analytics
GET /series
GET /species
Enter fullscreen mode Exit fullscreen mode

How do I handle nested resources?

Keep both levels plural:

GET /users/{userId}/orders
GET /pets/{petId}/vaccinations
GET /orders/{orderId}/items
Enter fullscreen mode Exit fullscreen mode

What if my team prefers singular?

Consistency is key. If your API is already standardized on singular, keep it. But for new APIs, use plural.

Does GraphQL use plural or singular?

GraphQL typically uses singular for single-item queries, plural for lists:

query {
  user(id: "123") { ... }      # Singular
  users(limit: 10) { ... }     # Plural
}
Enter fullscreen mode Exit fullscreen mode

GraphQL queries are explicit about returning one vs many.

How does Modern PetstoreAPI handle this?

Modern PetstoreAPI uses plural names for all REST endpoints. See the REST API guide for examples.

Can I test naming conventions automatically?

Yes, Apidog can run automated tests to check resource naming patterns. Import your OpenAPI spec and create naming test cases.

What about non-English APIs?

The plural rule applies for all languages. Use plurals according to your API’s language grammar. The principle—collections are plural—remains.

Top comments (0)