Skip to content

URI Naming

A URI is the name of a resource. Consistent naming lets a developer guess the next endpoint correctly without reading the docs — the highest compliment an API can earn.

  • Nouns, not verbs — /articles, never /getArticles. The method is the verb.
  • Plural collections — /articles is the collection; /articles/42 is one item in it. Pick plural and stick with it.
  • Lowercase with hyphens — /blog-posts, not /blogPosts or /Blog_Posts. Paths are case-sensitive in spirit; keep them lowercase to avoid surprises.
  • IDs in the path, not the query — /articles/42, not /articles?id=42. The query string is for filtering a collection, not identifying an item.
  • No file extensions — /articles/42, not /articles/42.json. Use the Accept header for format negotiation.
  • No trailing slash convention — choose with or without and be consistent (most APIs omit it).
GET /articles # collection
GET /articles/42 # one item
GET /articles/42/comments # that item's comments
GET /articles?status=draft # filtered collection
# Avoid:
GET /getArticles
GET /article/42 # inconsistent singular
GET /articles/42.json
GET /articles?articleId=42 # identity belongs in the path

Mixing naming conventions Symptom:

  • GET /userProfiles and GET /order-items in the same API
  • Developers have to remember which convention each endpoint uses
  • Pick one convention and stick to it — plural lowercase is most common

Putting the version in the wrong place Symptom:

  • /users/v2 — the version sits in the middle of the URI
  • /v1/users/v2/profile — versions nested inside each other
  • Always put the version at the start of the URI: /v1/users/\{id\}/profile

💡 Real-world examples

GitHub API:

  • /repos (plural), /issues, /pulls, /commits — consistently plural
  • /repos/\{owner\}/\{repo\}/git/refs — a clear hierarchy

Stripe API:

  • /payment_intents, /payment_methods, /setup_intents
  • snake_case used consistently across the whole API

Sources: GitHub REST API — repos, Stripe API reference

Which URI follows REST naming conventions for a single article?
Where does a resource identifier belong?
How should you choose between JSON and other formats?