DEV Community

Cover image for Designing URIs for REST APIs: The Cool, the Clean, and the Consistent
Athreya aka Maneshwar
Athreya aka Maneshwar

Posted on • Edited on

Designing URIs for REST APIs: The Cool, the Clean, and the Consistent

Hello, I'm Maneshwar. I'm building git-lrc, an AI code reviewer that runs on every commit. It is free, unlimited, and source-available on Github. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product.

---

You can’t build a great API without designing great URIs.

They’re not just strings – they’re the permanent addresses of your resources, the street names in the city of your service.

In this post, we’ll walk through time-tested patterns, practical dos and don’ts, and real-world techniques to keep your URIs clean, stable, and RESTful.

Design URIs That Make Sense

Problem:

How should I structure URIs so that they are predictable, readable, and RESTful?

Solution:

Follow standard conventions:

  • Use domains/subdomains to logically partition services.
  • Use slashes / for hierarchies (collections and sub-resources).
  • Use commas , and semicolons ; for non-hierarchical segments.
  • Use hyphens - or underscores _ for readability – pick one, stay consistent.
  • Use ampersands & in query strings to separate params.
  • Avoid file extensions like .php, .jsp, etc.

Domains and Subdomains

Use them to split responsibilities, locales, or access types:

http://en.example.org/book/1234   // English version
http://da.example.org/book/1234   // Danish version

http://www.example.org/book/1234  // for browsers
http://api.example.org/book/1234  // for API clients
Enter fullscreen mode Exit fullscreen mode

This lets you route traffic smartly – by region, by client type, even by infrastructure needs.

Slashes for Hierarchies

Use / like folders in a filesystem:

http://www.example.org/customers/1234/orders/5678
Enter fullscreen mode Exit fullscreen mode

This shows that order 5678 belongs to customer 1234.

Beware of trailing slashes though:

http://example.org/orders/  ✅  // Collection
http://example.org/orders   ✅  // Also valid
Enter fullscreen mode Exit fullscreen mode

Just be consistent. Some frameworks normalize these automatically, others don’t.

Hyphens vs Underscores

Pick one:

/blog/my-first-post   // hyphens = readable
/my_photos/our_trip   // underscores = valid too
Enter fullscreen mode Exit fullscreen mode

Most devs lean toward hyphens because they’re easier on the eyes and URLs like my-first-api just scan better.

Skip File Extensions

/report-summary.xml   // 👎 Don’t leak tech
/report-summary.jsp   // 👎 Even worse
/report-summary       // ✅ Let Accept header decide format
Enter fullscreen mode Exit fullscreen mode

File extensions tie your backend implementation to the URL – not great for flexibility or long-term sanity.

Query Parameters

Use them for filtering, pagination, options – not core identity.

/search?phrase=Antarctica&limit=10
Enter fullscreen mode Exit fullscreen mode

Use & to separate params, = for key-value. Easy.

Matrix Parameters (if you dare)

Rare but valid: semicolons ; and commas , can add structure without implying hierarchy.

/coordinates;lat=22.3;lng=88.6
Enter fullscreen mode Exit fullscreen mode

Don’t expect every framework to love this, though. Custom parsing is often required.

Use URIs as Opaque Identifiers

Problem:

How do I make URIs stable and unique without overloading them?

Solution:

  • Treat URIs as opaque keys – don’t inject too much meaning.
  • Avoid stateful hacks like repeatedly POSTing to the same URI to simulate a workflow.
  • Don’t overload semantics into headers or query strings that change behavior drastically.

Cool URIs Don’t Change

Problem:

How do I prevent URI breakage when things change under the hood?

Solution:

  • Design URIs based on stable concepts, not implementations.
  • Use server-side rewrite rules to hide internal changes.
  • If you must change URIs, use 301 redirects and keep old URIs alive.

Bad:

/api/v1/reports.jsp   // tech-coupled, versioned, fragile
Enter fullscreen mode Exit fullscreen mode

Good:

/api/reports/summary  // implementation-free
Enter fullscreen mode Exit fullscreen mode

If you later rewrite this part of your backend in Rust or Go, or if /api/v1 becomes /api/v2, you can:

  1. Leave the old URIs active with 301 redirects.
  2. Make the API version part of the Accept header (application/vnd.api+json;version=2).
  3. Use a gateway (e.g., API Gateway, Kong) to handle old-new mappings invisibly.

Cool URIs = happy clients = fewer breakages.

Bonus: Handle Special Characters Carefully

  • Space becomes %20 in RFC 3986, but + in application/x-www-form-urlencoded.
  • Be consistent with encoding.
  • Capital letters: Avoid them! URIs are case-sensitive after the host.
/search?phrase=Super+Collider         // Sent by HTML forms
/search?phrase=Super%20Collider       // Sent by JS fetch
Enter fullscreen mode Exit fullscreen mode

Always decode carefully on the backend. Normalize where possible.

Final Thoughts

Think of your API like a public library.

The URI is the shelf address.

If you keep rearranging shelves, nobody can find anything.

Follow conventions, stay consistent, and make your URIs boringly predictable.

Because boring = maintainable = scalable.


helps you get all your backend APIs documented in a few minutes

With , you can quickly generate interactive API documentation that allows users to search and execute APIs directly from the browser.

Return only the cleaned text without any additional commentary:

git-lrc
*AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.

git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.*

Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.

⭐ Star it on GitHub:

GitHub logo HexmosTech / git-lrc

Free, Unlimited AI Code Reviews That Run on Commit

git-lrc logo

git-lrc

Free, Unlimited AI Code Reviews That Run on Commit


git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt

AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.

git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.

See It In Action

See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements

git-lrc-intro-60s.mp4

Why

  • 🤖 AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production.
  • 🔍 Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong.
  • 🔁 Build a habit, ship better code. Regular review → fewer bugs → more robust code → better results in your team.
  • 🔗 Why git? Git is universal. Every editor, every IDE, every AI…




Top comments (1)

Collapse
 
nathan_tarbert profile image
Nathan Tarbert

been cool seeing steady progress - it adds up. you think the secret to keeping apis clean long-term is all about strict habits or more about picking one style and sticking to it?