[{"data":1,"prerenderedAt":743},["ShallowReactive",2],{"post-\u002Frest-api-uri-structure":3},{"page":4,"translation":628,"nav":630,"related":731,"random":736},{"id":5,"title":6,"body":7,"categories":610,"category":612,"date":613,"description":614,"draft":615,"extension":616,"image":617,"kind":612,"lang":618,"meta":619,"navigation":620,"path":256,"readingTime":621,"seo":622,"slug":623,"stem":623,"tags":624,"translationKey":623,"type":611,"updated":612,"__hash__":627},"posts\u002Frest-api-uri-structure.md","What Should the REST API URI Structure Be?",{"type":8,"value":9,"toc":599},"minimark",[10,74,85,88,91,96,229,231,238,293,295,299,302,312,325,340,342,346,349,364,366,370,376,378,382,385,553,565,567,570,573,584,586,591],[11,12,13,21],"blockquote",{},[14,15,16,17],"p",{},"💡 ",[18,19,20],"strong",{},"TL;DR:",[22,23,24,47,61],"ul",{},[25,26,27,30,31,35,36,39,40,35,43,46],"li",{},[18,28,29],{},"Rule 1:"," Use nouns (",[32,33,34],"code",{},"\u002Farticles",", ",[32,37,38],{},"\u002Fcomments","), not verbs (",[32,41,42],{},"\u002Fget",[32,44,45],{},"\u002Fdelete","), to name resources. The HTTP method (GET, POST, DELETE, etc.) already expresses the action.",[25,48,49,52,53,56,57,60],{},[18,50,51],{},"Rule 2:"," Prefer plural nouns (",[32,54,55],{},"\u002Fusers",") over singular ones in your URL hierarchy. Build that hierarchy with the slash ",[32,58,59],{},"\u002F",".",[25,62,63,66,67,69,70,73],{},[18,64,65],{},"Rule 3:"," Avoid trailing slashes (",[32,68,59],{},") and file extensions (",[32,71,72],{},".json",") at the end of your URIs.",[14,75,76,77,84],{},"This article is part of the ",[18,78,79],{},[80,81,83],"a",{"href":82},"\u002Frest-api-design","RESTful API Design"," series. If you haven't read the introductory post yet, I'd recommend starting there.",[14,86,87],{},"There is no hard-and-fast law for naming your endpoint addresses. There are, however, widely accepted guidelines—and they rest on sound reasoning. If you design your addresses around a consistent standard and a clear logic, documenting your API and onboarding its users becomes far easier. Otherwise, plenty of the developers consuming your API will be cursing your name. ;)",[89,90],"hr",{},[92,93,95],"h3",{"id":94},"rest-api-uri-right-and-wrong-examples","REST API URI: Right and Wrong Examples",[97,98,99,119],"table",{},[100,101,102],"thead",{},[103,104,105,110,113,116],"tr",{},[106,107,109],"th",{"align":108},"left","Operation \u002F Case",[106,111,112],{"align":108},"Wrong \u002F Bad URI Design",[106,114,115],{"align":108},"Right \u002F Standard URI Design",[106,117,118],{"align":108},"HTTP Method",[120,121,122,145,166,187,208],"tbody",{},[103,123,124,130,135,140],{},[125,126,127],"td",{"align":108},[18,128,129],{},"Get all articles",[125,131,132],{"align":108},[32,133,134],{},"\u002Fapi\u002FgetArticles",[125,136,137],{"align":108},[32,138,139],{},"\u002Fapi\u002Farticles",[125,141,142],{"align":108},[18,143,144],{},"GET",[103,146,147,152,157,162],{},[125,148,149],{"align":108},[18,150,151],{},"Get a specific article",[125,153,154],{"align":108},[32,155,156],{},"\u002Fapi\u002FgetArticle\u002F15",[125,158,159],{"align":108},[32,160,161],{},"\u002Fapi\u002Farticles\u002F15",[125,163,164],{"align":108},[18,165,144],{},[103,167,168,173,178,182],{},[125,169,170],{"align":108},[18,171,172],{},"Delete an article",[125,174,175],{"align":108},[32,176,177],{},"\u002Fapi\u002FdeleteArticle\u002F15",[125,179,180],{"align":108},[32,181,161],{},[125,183,184],{"align":108},[18,185,186],{},"DELETE",[103,188,189,194,199,204],{},[125,190,191],{"align":108},[18,192,193],{},"Get an article's comments",[125,195,196],{"align":108},[32,197,198],{},"\u002Fapi\u002Farticle\u002F15\u002FgetComments",[125,200,201],{"align":108},[32,202,203],{},"\u002Fapi\u002Farticles\u002F15\u002Fcomments",[125,205,206],{"align":108},[18,207,144],{},[103,209,210,215,220,225],{},[125,211,212],{"align":108},[18,213,214],{},"Specify a file format",[125,216,217],{"align":108},[32,218,219],{},"\u002Fapi\u002Farticles.json",[125,221,222,224],{"align":108},[32,223,139],{}," (via Accept header)",[125,226,227],{"align":108},[18,228,144],{},[89,230],{},[232,233,235],"h2",{"id":234},"the-full-series",[18,236,237],{},"The Full Series",[22,239,240,246,252,257,263,269,275,281,287],{},[25,241,242],{},[80,243,245],{"href":244},"\u002Frest-api-design#rest-api-basics","REST API Basics",[25,247,248],{},[80,249,251],{"href":250},"\u002Frest-api-design#output-format","What Should the REST API Output Format Be?",[25,253,254],{},[80,255,6],{"href":256},"\u002Frest-api-uri-structure",[25,258,259],{},[80,260,262],{"href":261},"\u002Fwhat-is-hateoas","What is HATEOAS in REST API?",[25,264,265],{},[80,266,268],{"href":267},"\u002Frest-api-authentication","How to Perform REST API Authentication?",[25,270,271],{},[80,272,274],{"href":273},"\u002Frest-api-error-handling","How to Perform REST API Error Handling?",[25,276,277],{},[80,278,280],{"href":279},"\u002Frest-api-security","How to Secure a REST API?",[25,282,283],{},[80,284,286],{"href":285},"\u002Frest-api-documentation-and-testing","How to Document and Test a REST API?",[25,288,289],{},[80,290,292],{"href":291},"\u002Ffull-stack-project-development","Sample REST API Project",[89,294],{},[232,296,298],{"id":297},"_1-use-nouns-to-define-resources","1. Use Nouns to Define Resources",[14,300,301],{},"In our endpoint addresses we should use nouns, not verbs (actions). That noun should be whatever object we're trying to read data from or operate on.",[14,303,304,305,308,309,60],{},"For example, for an endpoint that lists the articles on a blog, prefer ",[32,306,307],{},"https:\u002F\u002Fexample.com\u002Fapi\u002Farticles"," over ",[32,310,311],{},"https:\u002F\u002Fexample.com\u002Fapi\u002Fget-articles",[14,313,314,315,317,318,320,321,324],{},"This way the endpoint in the URL represents an object, while your HTTP method represents the action: ",[32,316,144],{}," -> Retrieve, ",[32,319,186],{}," -> Delete, ",[32,322,323],{},"PATCH"," -> Update, and so on.",[14,326,327,328,330,331,334,335,330,337,339],{},"Name your addresses like this and, to delete an article, you no longer send a ",[32,329,144],{}," request to ",[32,332,333],{},"\u002Fapi\u002Fdeletearticle\u002F15","—you send a ",[32,336,186],{},[32,338,161],{}," and achieve the same thing.",[89,341],{},[232,343,345],{"id":344},"_2-prefer-plural-nouns-not-singular","2. Prefer Plural Nouns, Not Singular",[14,347,348],{},"Generally speaking, \"article\" is a single resource, while \"articles\" is a collection of resources. Using collection names (plural) in your endpoint addresses is the better choice.",[14,350,351,352,330,354,357,358,330,360,363],{},"That way you can query all articles by sending a ",[32,353,144],{},[32,355,356],{},"example.com\u002Farticles",", or query a specific article with a ",[32,359,144],{},[32,361,362],{},"example.com\u002Farticles\u002F{articleId}",". The JSON:API specification also recommends using plural names.",[89,365],{},[232,367,369],{"id":368},"_3-resource-sub-collections","3. Resource Sub-collections",[14,371,372,373,60],{},"To query related sub-data belonging to a specific resource, you build hierarchical URI structures. For example, to query the comments on a specific article, we can send a request to ",[32,374,375],{},"example.com\u002Farticles\u002F{articleId}\u002Fcomments",[89,377],{},[232,379,381],{"id":380},"_4-stick-to-standards-and-conventions","4. Stick to Standards and Conventions",[14,383,384],{},"You may not want to follow the generally accepted conventions—but whatever your rule is, you should apply the same standard everywhere across your API. Here are some of the widely accepted conventions, several of which are also defined by JSON:API:",[386,387,388,429,453,478,486,513],"ol",{},[25,389,390,393,396,397,400,401,403,407],{},[18,391,392],{},"Use the slash (\u002F) character to express hierarchical relationships:",[394,395],"br",{},"\nThe slash character (\u002F) is used to express hierarchical links in addresses. If you're going to express hierarchy with underscores instead of slashes (e.g., ",[32,398,399],{},"article_15_comments","), then apply that rule everywhere in the API.",[394,402],{},[404,405,406],"em",{},"Standard examples using slashes:",[22,408,409,414,419,424],{},[25,410,411],{},[32,412,413],{},"https:\u002F\u002Fexample.com\u002Fblog-admin\u002Farticles",[25,415,416],{},[32,417,418],{},"https:\u002F\u002Fexample.com\u002Fblog-admin\u002Farticles\u002F{articleId}",[25,420,421],{},[32,422,423],{},"https:\u002F\u002Fexample.com\u002Fblog-admin\u002Farticles\u002F{articleId}\u002Fcomments",[25,425,426],{},[32,427,428],{},"https:\u002F\u002Fexample.com\u002Fblog-admin\u002Farticles\u002F{articleId}\u002Fcomments\u002F{commentId}",[25,430,431,434,436,437,439,440],{},[18,432,433],{},"Don't use unnecessary trailing slashes in URIs:",[394,435],{},"\nThe ",[32,438,59],{}," character you add to the end of an address carries no meaning and can cause incompatibilities between systems.",[22,441,442,448],{},[25,443,444,445],{},"Bad: ",[32,446,447],{},"https:\u002F\u002Fexample.com\u002Fblog-admin\u002Farticles\u002F",[25,449,450,451],{},"Good: ",[32,452,413],{},[25,454,455,458,460,461,463,466,468,469,472,473,475],{},[18,456,457],{},"Improving readability (word separation):",[394,459],{},"\nJSON:API recommends that if resource names consist of more than one word, we separate them using camelCase:",[394,462],{},[32,464,465],{},"https:\u002F\u002Fexample.com\u002Fusers\u002F15\u002FdeviceDetails",[394,467],{},"\nThat said, in URL standards the hyphen (",[32,470,471],{},"-",") character (kebab-case) is more widely accepted and is SEO-friendly:",[394,474],{},[32,476,477],{},"https:\u002F\u002Fexample.com\u002Fusers\u002F15\u002Fdevice-details",[25,479,480,483,485],{},[18,481,482],{},"Use lowercase letters:",[394,484],{},"\nRFC 3986 defines URIs as case-sensitive for the paths beyond the domain name. To avoid confusion, always adopt the lowercase standard.",[25,487,488,491,493,494,497,498,501,502],{},[18,489,490],{},"Don't use file extensions:",[394,492],{},"\nFile extensions look bad and serve no function whatsoever. If you want to specify the media type (Content-Type) of the response, do it via the ",[32,495,496],{},"Accept"," and ",[32,499,500],{},"Content-Type"," values in the HTTP header—not via a file extension:",[22,503,504,509],{},[25,505,444,506],{},[32,507,508],{},"https:\u002F\u002Fexample.com\u002Fusers\u002F15\u002FdeviceDetails.json",[25,510,450,511],{},[32,512,465],{},[25,514,515,518,520,521],{},[18,516,517],{},"Unicode characters:",[394,519],{},"\nIn URIs and JSON keys, you should only use these safe ASCII character ranges:",[22,522,523,529,535,541],{},[25,524,525,528],{},[32,526,527],{},"a-z"," (U+0061 to U+007A)",[25,530,531,534],{},[32,532,533],{},"A-Z"," (U+0041 to U+005A)",[25,536,537,540],{},[32,538,539],{},"0-9"," (U+0030 to U+0039)",[25,542,543,544,546,547,550,552],{},"Hyphen ",[32,545,471],{}," and Underscore ",[32,548,549],{},"_",[394,551],{},"\nUsing URL-unsafe spaces, or Turkish\u002FUnicode characters directly in URIs, can lead to server errors.",[14,554,555,556,60],{},"For more detail, you can review the ",[80,557,564],{"href":558,"rel":559,"target":563},"https:\u002F\u002Fjsonapi.org\u002F",[560,561,562],"nofollow","noopener","noreferrer","_blank","JSON:API documentation",[89,566],{},[14,568,569],{},"That's all I have to share on endpoint addresses for now. I'll add new practices as they come to mind. If you have questions or anything to add, feel free to share in the comments.",[14,571,572],{},"In the next part we'll cover authentication, but before that I'd recommend reading the HATEOAS concept I added to this series later on.",[22,574,575,580],{},[25,576,577],{},[80,578,579],{"href":261},"REST API and the HATEOAS Concept",[25,581,582],{},[80,583,268],{"href":267},[89,585],{},[587,588,590],"h5",{"id":589},"changelog","Changelog",[22,592,593,596],{},[25,594,595],{},"2022-05-11: Article summary revised.",[25,597,598],{},"2026-06-21: Fixed Turkish spelling and typos; removed invalid trailing space characters at the ends of URLs. Enriched the article with a TL;DR summary panel and a comparison table showing right vs. wrong URI designs.",{"title":600,"searchDepth":601,"depth":601,"links":602},"",2,[603,605,606,607,608,609],{"id":94,"depth":604,"text":95},3,{"id":234,"depth":601,"text":237},{"id":297,"depth":601,"text":298},{"id":344,"depth":601,"text":345},{"id":368,"depth":601,"text":369},{"id":380,"depth":601,"text":381},[611],"technical",null,"2026-06-20","Rules for resource-oriented endpoints in REST API design — plural nouns, hierarchy, and the conventions that keep URIs predictable.",false,"md","\u002Fimages\u002Fhero\u002Frest-api-uri.avif","en",{},true,5,{"title":6,"description":614},"rest-api-uri-structure",[625,626],"api","rest","pQGHqkFz5FfLlCKoJLwmNpM8O9lfc0lLPCaoNuprHh0",{"path":629},"\u002Ftr\u002Frest-api-uri-yapisi-nasil-olmali",{"prev":631,"next":632,"others":635,"lucky":730,"readingTime":621},{"path":279,"title":280},{"path":633,"title":634},"\u002Ftroubleshooting-cyberpanel-inaccessibility-after-ubuntu-release-upgrade","Troubleshooting CyberPanel Inaccessibility After Ubuntu Release Upgrade",[636,637,638,640,641,642,643,644,647,650,653,656,659,662,665,668,671,674,677,680,683,686,689,692,695,698,701,704,707,710,713,716,719,722,724,727],{"path":291,"title":292},{"path":267,"title":268},{"path":82,"title":639},"REST API Design: Principles and Output Format",{"path":285,"title":286},{"path":273,"title":274},{"path":279,"title":280},{"path":633,"title":634},{"path":645,"title":646},"\u002Freset-wordpress-admin-password-using-wp-cli","Reset WordPress Admin Password Using WP-CLI",{"path":648,"title":649},"\u002Fgraphql-vs-rest-api-which-is-the-best-choice-for-headless-wordpress","GraphQL vs REST API: Which is the Best Choice for Headless WordPress?",{"path":651,"title":652},"\u002Fgrow-your-business-in-turkey-with-expert-wordpress-plugin-and-theme-localization-and-support-services","Grow Your Business in Turkey with Expert WordPress Plugin and Theme Localization and Support Services",{"path":654,"title":655},"\u002Fgetting-started-with-devops-understanding-the-principles-and-adopting-the-tools","Getting Started with DevOps: Understanding the Principles and Adopting the Tools",{"path":657,"title":658},"\u002Fphp-graphql-development-advanced-techniques-for-optimizing-your-apis","PHP GraphQL Development: Advanced Techniques for Optimizing Your APIs",{"path":660,"title":661},"\u002Fadvanced-techniques-for-dependency-injection-in-php-tips-code-samples-and-faqs","Advanced Techniques for Dependency Injection in PHP: Tips, Code Samples, and FAQs",{"path":663,"title":664},"\u002Fmaximize-the-potential-of-headless-wordpress-with-graphql","Maximize the Potential of Headless WordPress with GraphQL",{"path":666,"title":667},"\u002Fwriting-clean-modular-and-reusable-code-in-php","Best Practices for Writing Clean, Modular, and Reusable Code in PHP",{"path":669,"title":670},"\u002Fheadless-cmss-an-overview-of-popular-alternatives-to-contentful-and-wordpress","Headless CMSs: An Overview of Popular Alternatives to Contentful and WordPress",{"path":672,"title":673},"\u002Fci-cd-for-php-a-comprehensive-guide","CI\u002FCD for PHP: A Comprehensive Guide",{"path":675,"title":676},"\u002Fintroduction-to-php-namespaces-a-beginners-guide-to-structuring-your-code","Introduction to PHP Namespaces: A Beginner's Guide to Structuring Your Code",{"path":678,"title":679},"\u002Fwhat-is-graylog-a-powerful-tool-for-collecting-indexing-and-analyzing-log-data","What is Graylog? A Powerful Tool for Collecting, Indexing, and Analyzing Log Data",{"path":681,"title":682},"\u002Felevate-your-turkish-audience-experience-with-professional-wordpress-plugin-and-theme-translation","Elevate Your Turkish Audience Experience with Professional WordPress Plugin and Theme Translation",{"path":684,"title":685},"\u002Fhow-to-set-up-a-self-hosted-api-gateway-a-comprehensive-guide","How to Set Up a Self-Hosted API Gateway: A Comprehensive Guide",{"path":687,"title":688},"\u002Fdifference-between-generators-and-iterators-in-php","The Key Differences Between PHP Generators and Iterators",{"path":690,"title":691},"\u002Fphp-and-machine-learning-a-winning-combination-with-php-ml","PHP and Machine Learning: A Winning Combination with PHP-ML",{"path":693,"title":694},"\u002Fphp-generators-a-beginners-guide-to-iteration","PHP Generators: A Beginner's Guide to Iteration",{"path":696,"title":697},"\u002Fmastering-closures-in-javascript-a-beginners-guide","Mastering Closures in JavaScript: A Beginner's Guide",{"path":699,"title":700},"\u002Fthe-top-php-certification-programs-for-developers","The Top PHP Certification Programs for Developers",{"path":702,"title":703},"\u002Fhow-to-revalidate-next-js-isr-cache-on-demand-cache-regeneration","How to Revalidate Next.js ISR Cache? On-Demand Cache Regeneration",{"path":705,"title":706},"\u002Ftips-for-translating-a-wordpress-plugin-wordpress-theme-to-turkish","Tips for Translating a WordPress Plugin \u002F WordPress Theme to Turkish",{"path":708,"title":709},"\u002Fall-about-headless-wordpress","All About Headless WordPress",{"path":711,"title":712},"\u002Finstall-composer-on-ubuntu","How to Install Composer on Ubuntu \u002F Linux",{"path":714,"title":715},"\u002Fwhat-is-an-api-gateway","What is an API Gateway? Should You Use It?",{"path":717,"title":718},"\u002Fis-jwt-safe-or-is-it-vulnerable","Is JWT Safe or Is It Vulnerable?",{"path":720,"title":721},"\u002Ftailwind-css-to-use-or-not-to-use-that-is-the-question","Tailwind CSS! To use? Or not to use? That is the question.",{"path":261,"title":723},"What is HATEOAS?",{"path":725,"title":726},"\u002Fhello-world","Hello World: A New Multilingual Journey",{"path":728,"title":729},"\u002Fwhat-is-ecmascript","What is ECMAScript? What is not?",{"path":261,"title":723},[732,733,734,735],{"path":291,"title":292,"date":613},{"path":267,"title":268,"date":613},{"path":82,"title":639,"date":613},{"path":285,"title":286,"date":613},[737,739,741],{"path":684,"title":685,"date":738},"2023-01-12",{"path":717,"title":718,"date":740},"2022-05-12",{"path":648,"title":649,"date":742},"2023-01-24",1782141978737]