{"id":21025,"date":"2016-04-27T07:00:36","date_gmt":"2016-04-27T14:00:36","guid":{"rendered":"https:\/\/www.jamasoftware.com\/?p=21025"},"modified":"2023-01-12T16:55:38","modified_gmt":"2023-01-13T00:55:38","slug":"rest-api-design","status":"publish","type":"post","link":"https:\/\/www.jamasoftware.com\/legacy\/blog\/2016\/04\/27\/rest-api-design\/","title":{"rendered":"REST API Design"},"content":{"rendered":"<p>Designing a REST API isn\u2019t easy. Anyone who claims differently either hasn\u2019t designed one, hasn&#8217;t designed one for a moderately complex system, or is a rare genius who has never found anything to be challenging in their lives. One can set out determined to adhere to\u00a0<a href=\"https:\/\/codeplanetio.wordpress.com\/2013\/12\/31\/principles-good-restful-api-design\/\" target=\"_blank\" rel=\"noopener\">REST design principles<\/a>\u00a0where a client user can intuitively find the endpoints they need, where all \u201cobjects\u201d in the system are represented as resources that can be acted upon with one of four HTTP operations (POST, GET, PUT, DELETE) and users can do whatever they\u2019re trying to achieve with as few calls as possible. But challenges will appear. Immediately.<\/p>\n<p>A couple years ago at Jama, we set out to build a new REST API to eventually replace all our SOAP and\u00a0<a href=\"http:\/\/directwebremoting.org\/dwr\/index.html\">DWR<\/a>\u00a0interfaces. Two key design challenges were:<\/p>\n<ul>\n<li>Chatty vs. Chunky API Design<\/li>\n<li>Modeling Resources vs. Business Processes<\/li>\n<\/ul>\n<p>The second challenge is difficult, and it\u2019s one I could talk about all day (and perhaps I will in a later post). But, today I\u2019m going to focus on the Chatty vs. Chunky problem.<\/p>\n<p><strong>Chatty vs. Chunky APIs<\/strong><\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-21029 size-full\" src=\"https:\/\/static.jamasoftware.com\/www\/imports\/2016\/04\/blog-image-chunky-chatty.jpg\" alt=\"REST API\" width=\"856\" height=\"573\" \/><\/p>\n<p>It wasn\u2019t long after people started writing against our initial iteration of the API, that the conversation about \u201cchattiness\u201d came up. API developers have been having conversations about\u00a0<a href=\"http:\/\/apigee.com\/about\/blog\/technology\/restful-api-design-chatty-apis\">this<\/a>\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Service_Granularity_Principle\">concept<\/a>\u00a0<a href=\"https:\/\/www.thoughtworks.com\/insights\/blog\/rest-api-design-resource-modeling\">all<\/a>\u00a0<a href=\"http:\/\/www.infoworld.com\/article\/2619514\/cloud-computing\/lack-of-good-api-design-hurts-the-cloud.html\">over<\/a>\u00a0<a href=\"http:\/\/shajisethu.blogspot.com\/2006\/01\/chatty-or-chunky-interfaces.html\">the<\/a>\u00a0<a href=\"https:\/\/depts.washington.edu\/ontheroa\/?p=343\">web<\/a>, but the essence of it is this: Users need to get the data they are after in as few calls as possible. If they have to make too many smaller calls to get all the data they seek, then the API is too \u201cchatty\u201d for their needs. On the other hand, if API calls are too large, and return more data than is needed, the API can be considered too \u201cchunky\u201d. The two ends of this spectrum are also referred to as Fine Grained vs Coarse Grained APIs.The user call would look something like this:<\/p>\n<p>Let\u2019s give an example to illustrate this. Say I have an API call to retrieve user comments on a blog. Comments can be made on a blog post, so, if they are, they should have a\u00a0<em>page<\/em>\u00a0property to indicate the page they appear on. They should also have an <em>author<\/em>\u00a0field to indicate who made the comment.<\/p>\n<p>The user call would look something like this:<\/p>\n<pre><code class=\"javascript\">GET \/comments?page=27<\/code><\/pre>\n<p>And the JSON data in the response might look something like this:<\/p>\n<pre><code class=\"json\">[\r\n  {\r\n    \"id\": \"796\",\r\n    \"author\": \"23\",\r\n    \"page\": \"27\",\r\n    \"createdDate\": \"2016-04-08T09:15:00\",\r\n    \"text\": \"This blog page changed me for the better. I've never read anything quite like it.\"\r\n  },\r\n  {\r\n    \"id\": \"1097\",\r\n    \"author\": \"1\",\r\n    \"page\": \"27\",\r\n    \"createdDate\": \"2016-04-08T16:15:00\",\r\n    \"text\": \"I agree! Thanks for posting!\",\r\n    \"inReplyTo\": \"796\"\r\n  }\r\n]<\/code><\/pre>\n<p>This example is overly simplified, but you can see in\u00a0the comment, the author properties have the values\u00a0<code>23<\/code>\u00a0and\u00a0<code>1<\/code>\u00a0which you can assume are the authors\u2019 unique user IDs. Similarly, the blog page these comments are on is being referred to by its page ID of <code>27<\/code>. The second comment is also in reply to some other person\u2019s comment, so that\u00a0<code>inReplyTo<\/code>\u00a0property has a value of\u00a0<code>796<\/code> to reference another comment ID.<\/p>\n<p>This payload is very short and simple, but it presents some problems if the API user is interested in knowing more about the author than just the author\u2019s user ID (you can be sure that they at least want to know the author\u2019s name!)<\/p>\n<p>First, if you\u2019re the user of this API, you\u2019re not given any indication of how to retrieve the complete user information associated with user ID\u00a0<code>1<\/code>, nor the complete information for what content is on page ID\u00a0<code>27<\/code>. This is a problem with \u201cdiscoverability.\u201d<\/p>\n<p>But even if that discoverability problem is solved, you would still need to make a separate API call to retrieve that user. Further, if you are retrieving a collection of hundreds of comments, you would potentially need to make a user call for each comment you retrieve. You would need to make hundreds calls to the API to get the information you\u2019re looking for. Hence the term \u201cchatty\u201d.<\/p>\n<p>But let\u2019s look at the other end of the spectrum. The API could attach the complete information of all object properties to the response and you\u2019d get something like this:<\/p>\n<pre><code class=\"json\">[\r\n  {\r\n    \"author\": {\r\n      \"id\": \"23\",\r\n      \"active\": \"true\",\r\n      \"firstName\": \"Lisa\",\r\n      \"lastName\": \"Turtle\",\r\n      \"avatarUrl\": \"http:\/\/base_url.com\/lisa.jpg\",\r\n      \"registrationDate\": \"2012-04-19T09:16:00\",\r\n      \"hobbies\": \"It's turtles all the way down\"\r\n    },\r\n    \"page\": {\r\n      \"id\": \"27\",\r\n      \"title\": \"The Meaning of Life\",\r\n      \"createdDate\": \"2016-04-07T14:07:00\",\r\n      \"author\": {\r\n       ...another user object...\r\n      }\r\n      ...and so on...\r\n    },\r\n    \"createdDate\": \"2016-04-08T09:15:00\",\r\n    \"text\": \"This blog page changed me for the better. I've never read anything quite like it.\"\r\n  },\r\n  {\r\n    \"author\": {\r\n      \"id\": \"1\",\r\n      \"active\": \"true\",\r\n      \"firstName\": \"Jason\",\r\n      \"lastName\": \"Goetz\",\r\n      \"avatarUrl\": \"https:\/\/www.jamasoftware.com\/app\/uploads\/2016\/04\/FEAT-Jason.jpg\",\r\n      \"registrationDate\": \"2004-02-19T07:16:00\",\r\n      \"hobbies\": \"Public debate, dancing, skeet shooting\"\r\n    },\r\n    \"page\": {\r\n      \"id\": \"27\",\r\n      \"title\": \"The Meaning of Life\",\r\n      \"createdDate\": \"2016-04-07T14:07:00\",\r\n      \"author\": {\r\n        ...another user object...\r\n      }\r\n      ...and so on...\r\n    },\r\n    \"createdDate\": \"2016-04-08T16:15:00\",\r\n    \"text\": \"I agree! Thanks for posting!\",\r\n    \"inReplyTo\": {\r\n      ...the first comment data repeated again?...\r\n    }\r\n  }\r\n]<\/code><\/pre>\n<p>As the API user, you now have all the information you need. The full\u00a0author\u00a0information is available, you know the full details of the blog page that the comment was posted on, and you can even see the entire other comment that this comment was in reply to directly in the\u00a0<code>inReplyTo<\/code> value.<\/p>\n<p>But you have a myriad of new problems.<\/p>\n<p>The first is the sheer size of the payload returned. This is a fairly simplified example. User and page objects would likely have many more properties than these examples show. If you are retrieving hundreds of comments and you\u2019re getting a full object for every property on each comment, this is going to be a lot of data. As the client user, you may not have bandwidth concerns about getting this much data across the wire, but it certainly could take the server more time to assemble all that data, and long-running transactions are much harder on a server\u2019s CPU &amp; memory. Especially when the server is dealing with multiple concurrent requests.<\/p>\n<p>It should also be noted, if it turns out that 99 out of 100 retrieved comments were all authored by the same user and all the comments are posted on the same page, then most of the\u00a0user\u00a0and\u00a0page\u00a0objects in your results are going to be redundant. The time the server spent assembling\u00a0user\u00a0and\u00a0page\u00a0data was mostly wasted.<\/p>\n<p>Data inconsistencies are also bound to come up. In this case, what if there aren\u2019t any restrictions on how many embedded replies you can have in your comments section? If someone replies to the first comment, then someone replies to that reply, then someone replies to that reply\u2026 you get the point. How should that data be represented? You could choose to go one level deep but API users may be confused about the point at which the API decides to cut off the addition of further data, and how they should write a client to consume it.<\/p>\n<p>These are the problems with a chunky API.<\/p>\n<p>The API could also try to find some kind of compromise and attach only partial data. While the full author\u2019s info may be retrievable from some user call, the comment payload may only contain the author\u2019s user ID, first name, and last name.<\/p>\n<p>But, there are problems with this approach as well (this all sounds so negative!). Inconsistent partial objects make it harder to intuitively work with the API. The same inconsistencies described with the\u00a0inReplyTo\u00a0example above apply here as well. Also, the API may not provide the data you are looking for in the first place. If you just want the author\u2019s name and avatar, but the avatar isn\u2019t provided, you\u2019ll still need to make a separate call to get the full\u00a0user\u00a0object just so you have that data.<\/p>\n<p>So, what\u2019s the best approach then?<\/p>\n<h4>The Solution<\/h4>\n<p>When making design decisions and facing a spectrum like this where both ends of the spectrum provide their own challenges, we can only strive to find balance and be practical. We need to find a solution to the Chatty\u00a0API design problems while avoiding going down the Chunky API route. We want to remain simple, clean, and RESTful. We also want to make our API flexible enough to allow users to meet their own needs in the chatty to chunky continuum.<\/p>\n<p>While the \u201cpartial data\u201d example\u00a0above attempts to find a compromise between Chatty and Chunky, I\u2019ve already pointed out some issues with a compromised\u00a0approach. Instead of compromising, what if we instead adhere to everything we like about the chatty API model, but give users the extra facilities to add data to their response?<\/p>\n<p>Let\u2019s look at another approach. With this approach, the calling user makes a request for comments, but specifies they would like the author field included as well:<\/p>\n<pre><code class=\"javascript\">GET \/comments?page=27&amp;include=data.author<\/code><\/pre>\n<p>The response would look like this:<\/p>\n<pre><code class=\"json\">{\r\n  \"links\": {\r\n    \"data.author\": {\r\n      \"type\": \"user\",\r\n      \"href\": \"http:\/\/base_url.com\/comments\/{data.author}\"\r\n    },\r\n    \"data.page\": {\r\n      \"type\": \"page\",\r\n      \"href\": \"http:\/\/base_url.com\/comments\/{data.page}\"\r\n    },\r\n    \"data.inReplyTo\": {\r\n      \"type\": \"comment\",\r\n      \"href\": \"http:\/\/base_url.com\/comments\/{data.inReplyTo}\"\r\n    }\r\n  },\r\n  \"linked\": {\r\n    \"user\": {\r\n      \"1\": {\r\n        \"id\": \"1\",\r\n        \"active\": \"true\",\r\n        \"firstName\": \"Jason\",\r\n        \"lastName\": \"Goetz\",\r\n        \"avatarUrl\": \"https:\/\/www.jamasoftware.com\/app\/uploads\/2016\/04\/FEAT-Jason.jpg\",\r\n        \"registrationDate\": \"2004-02-19T07:16:00\",\r\n        \"hobbies\": \"Public debate, dancing, skeet shooting\"\r\n      },\r\n      \"23\": {\r\n        \"id\": \"23\",\r\n        \"active\": \"true\",\r\n        \"firstName\": \"Lisa\",\r\n        \"lastName\": \"Turtle\",\r\n        \"avatarUrl\": \"http:\/\/base_url.com\/lisa.jpg\",\r\n        \"registrationDate\": \"2012-04-19T09:16:00\",\r\n        \"hobbies\": \"It's turtles all the way down\"\r\n      }\r\n    }\r\n  },\r\n  \"data\": [\r\n    {\r\n      \"id\": \"796\",\r\n      \"author\": \"23\",\r\n      \"page\": \"27\",\r\n      \"createdDate\": \"2016-04-08T09:15:00\",\r\n      \"text\": \"This blog page changed me for the better. I've never read anything quite like it.\"\r\n    },\r\n    {\r\n      \"id\": \"1097\",\r\n      \"author\": \"1\",\r\n      \"page\": \"27\",\r\n      \"createdDate\": \"2016-04-08T16:15:00\",\r\n      \"text\": \"I agree! Thanks for posting!\",\r\n      \"inReplyTo\": \"796\"\r\n    }\r\n  ]\r\n}<\/code><\/pre>\n<p>This is a lot to ingest at once, but the payoff is worth it. You can see here that the comments payload is now listed under\u00a0<code>data<\/code>. Also, there are now separate properties in the response called\u00a0<code>links<\/code>\u00a0and\u00a0<code>linked<\/code>.<\/p>\n<p>The\u00a0<code>data<\/code>\u00a0section is exactly the same as the one given under the Chatty API example above. But, with the helpful\u00a0<code>links<\/code>\u00a0and\u00a0<code>linked<\/code>\u00a0properties, the lack of associated data is much less of an issue.<\/p>\n<p>The\u00a0<code>links<\/code>\u00a0section takes care of the \u201cdiscoverability\u201d problem I mentioned above. For any property that simply displays an ID (like\u00a0<code>author<\/code>,\u00a0<code>page<\/code>\u00a0and\u00a0<code>inReplyTo<\/code>) the links section will describe how you can plug that ID into a separate API call to retrieve the information you\u2019re seeking.<\/p>\n<p>The\u00a0<code>linked<\/code>\u00a0section is where we really begin to solve the problems associated with Chatty APIs. In the request, you have asked to include any\u00a0<code>user<\/code>\u00a0objects that are referenced in any of the comment\u00a0<code>author<\/code>\u00a0fields. The resulting response now gives a data store of\u00a0<code>user<\/code>\u00a0objects in the\u00a0<code>linked<\/code>\u00a0section for any user IDs specified under\u00a0<code>author<\/code>. This removes the need to make any further calls to the\u00a0<code>users<\/code>\u00a0endpoint to get all the information you\u2019re seeking. But it also solves the redundancy problems since a user will only appear once per user ID. In other words, you could have 99 comments where the\u00a0<code>author<\/code>\u00a0value is the same, but you\u2019d only have one inclusion of that author\u2019s data in the\u00a0<code>linked<\/code>\u00a0section. This also (potentially) takes less time for the server to assemble than a full attachment of all\u00a0<code>author<\/code>\u00a0data to each individual comment since we\u2019re only loading and assembling the\u00a0<code>author<\/code>\u00a0data once for the data store.<\/p>\n<p>This solution offers the simplicity of the chatty API at its base. It\u2019s only giving you the basic information you\u2019re requesting. But, it additionally gives you discoverability and the flexibility to ask for further data in the same request so we solve the main problems associated with chatty APIs. We\u2019ve managed to address all of these previously mentioned problems:<\/p>\n<ul>\n<li>Discoverability<\/li>\n<li>Not enough data i.e. the need for repeated API calls or chattiness<\/li>\n<li>Large payloads associated with chunky APIs<\/li>\n<li>Server processing time associated with chunky APIs<\/li>\n<li>Redundancy<\/li>\n<\/ul>\n<p>Here at Jama, while designing our REST API, we\u2019ve set out to find balance in our API design with an emphasis on ease-of-use, practicality and flexibility for our users. This chatty vs chunky tradeoff is just one aspect of the challenges we face to build an API that works for us and our users. We\u2019ve come up with a REST JSON response data structure very similar to the one in the example above. It allows us to be uncompromising in resources being clean and lean, while still allowing our users to retrieve the data they seek. It\u2019s loosely based on an initial version of the\u00a0<a href=\"http:\/\/jsonapi.org\/\">JSON API<\/a>\u00a0specification and we feel it elegantly satisfies our and our users\u2019 needs.<\/p>\n<p>Comments? Questions? I\u2019d love to hear your feedback!<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Designing a REST API isn\u2019t easy. Anyone who claims differently either hasn\u2019t designed one, hasn&#8217;t designed one for a moderately complex system, or is a rare genius who has never found anything to be challenging in their lives. One can set out determined to adhere to\u00a0REST design principles\u00a0where a client user can intuitively find the [&hellip;]<\/p>\n","protected":false},"author":79,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[847,849],"tags":[180,172],"industry":[],"class_list":["post-21025","post","type-post","status-publish","format-standard","hentry","category-ecosystem","category-integrations","tag-breakthecode","tag-rest-api"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.1 (Yoast SEO v28.1) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>REST API Design - Jama Software<\/title>\n<meta name=\"description\" content=\"Designing a REST API isn\u2019t easy. Anyone who claims differently either hasn\u2019t designed one, hasn&#039;t designed one for a complex system, or is a rare genius.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"REST API Design\" \/>\n<meta property=\"og:description\" content=\"Designing a REST API isn\u2019t easy. Anyone who claims differently either hasn\u2019t designed one, hasn&#039;t designed one for a complex system, or is a rare genius.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/\" \/>\n<meta property=\"og:site_name\" content=\"Jama Software\" \/>\n<meta property=\"article:published_time\" content=\"2016-04-27T14:00:36+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-01-13T00:55:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/static.jamasoftware.com\/www\/imports\/2016\/04\/blog-image-chunky-chatty.jpg\" \/>\n<meta name=\"author\" content=\"Steve Gotsch\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Steve Gotsch\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/\"},\"author\":{\"name\":\"Steve Gotsch\",\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/#\\\/schema\\\/person\\\/abe0886b233c2813a679c04066e034b8\"},\"headline\":\"REST API Design\",\"datePublished\":\"2016-04-27T14:00:36+00:00\",\"dateModified\":\"2023-01-13T00:55:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/\"},\"wordCount\":1811,\"image\":{\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/static.jamasoftware.com\\\/www\\\/imports\\\/2016\\\/04\\\/blog-image-chunky-chatty.jpg\",\"keywords\":[\"#BreakTheCode\",\"REST API\"],\"articleSection\":[\"Ecosystem\",\"Integrations\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/\",\"url\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/\",\"name\":\"REST API Design - Jama Software\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/static.jamasoftware.com\\\/www\\\/imports\\\/2016\\\/04\\\/blog-image-chunky-chatty.jpg\",\"datePublished\":\"2016-04-27T14:00:36+00:00\",\"dateModified\":\"2023-01-13T00:55:38+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/#\\\/schema\\\/person\\\/abe0886b233c2813a679c04066e034b8\"},\"description\":\"Designing a REST API isn\u2019t easy. Anyone who claims differently either hasn\u2019t designed one, hasn't designed one for a complex system, or is a rare genius.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/#primaryimage\",\"url\":\"https:\\\/\\\/static.jamasoftware.com\\\/www\\\/imports\\\/2016\\\/04\\\/blog-image-chunky-chatty.jpg\",\"contentUrl\":\"https:\\\/\\\/static.jamasoftware.com\\\/www\\\/imports\\\/2016\\\/04\\\/blog-image-chunky-chatty.jpg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/2016\\\/04\\\/27\\\/rest-api-design\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.jamasoftware.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"REST API Design\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/#website\",\"url\":\"https:\\\/\\\/www.jamasoftware.com\\\/\",\"name\":\"Jama Software\",\"description\":\"Jama Connect\u00ae #1 in Requirements Management\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.jamasoftware.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.jamasoftware.com\\\/#\\\/schema\\\/person\\\/abe0886b233c2813a679c04066e034b8\",\"name\":\"Steve Gotsch\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ed6bf3d28ffe416f991a6120e565840a44526b876780afda309e084ca28cf340?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ed6bf3d28ffe416f991a6120e565840a44526b876780afda309e084ca28cf340?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/ed6bf3d28ffe416f991a6120e565840a44526b876780afda309e084ca28cf340?s=96&d=mm&r=g\",\"caption\":\"Steve Gotsch\"},\"description\":\"Steve Gotsch is an experienced product manager who writes about Jama Software's REST API and how to connect best-in-breed tools across the product development lifecycle.\",\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/in\\\/steve-gotsch\\\/\"],\"url\":\"https:\\\/\\\/www.jamasoftware.com\\\/blog\\\/author\\\/sgotsch\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"REST API Design - Jama Software","description":"Designing a REST API isn\u2019t easy. Anyone who claims differently either hasn\u2019t designed one, hasn't designed one for a complex system, or is a rare genius.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/","og_locale":"en_US","og_type":"article","og_title":"REST API Design","og_description":"Designing a REST API isn\u2019t easy. Anyone who claims differently either hasn\u2019t designed one, hasn't designed one for a complex system, or is a rare genius.","og_url":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/","og_site_name":"Jama Software","article_published_time":"2016-04-27T14:00:36+00:00","article_modified_time":"2023-01-13T00:55:38+00:00","og_image":[{"url":"https:\/\/static.jamasoftware.com\/www\/imports\/2016\/04\/blog-image-chunky-chatty.jpg","type":"","width":"","height":""}],"author":"Steve Gotsch","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Steve Gotsch","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/#article","isPartOf":{"@id":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/"},"author":{"name":"Steve Gotsch","@id":"https:\/\/www.jamasoftware.com\/#\/schema\/person\/abe0886b233c2813a679c04066e034b8"},"headline":"REST API Design","datePublished":"2016-04-27T14:00:36+00:00","dateModified":"2023-01-13T00:55:38+00:00","mainEntityOfPage":{"@id":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/"},"wordCount":1811,"image":{"@id":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/#primaryimage"},"thumbnailUrl":"https:\/\/static.jamasoftware.com\/www\/imports\/2016\/04\/blog-image-chunky-chatty.jpg","keywords":["#BreakTheCode","REST API"],"articleSection":["Ecosystem","Integrations"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/","url":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/","name":"REST API Design - Jama Software","isPartOf":{"@id":"https:\/\/www.jamasoftware.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/#primaryimage"},"image":{"@id":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/#primaryimage"},"thumbnailUrl":"https:\/\/static.jamasoftware.com\/www\/imports\/2016\/04\/blog-image-chunky-chatty.jpg","datePublished":"2016-04-27T14:00:36+00:00","dateModified":"2023-01-13T00:55:38+00:00","author":{"@id":"https:\/\/www.jamasoftware.com\/#\/schema\/person\/abe0886b233c2813a679c04066e034b8"},"description":"Designing a REST API isn\u2019t easy. Anyone who claims differently either hasn\u2019t designed one, hasn't designed one for a complex system, or is a rare genius.","breadcrumb":{"@id":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/#primaryimage","url":"https:\/\/static.jamasoftware.com\/www\/imports\/2016\/04\/blog-image-chunky-chatty.jpg","contentUrl":"https:\/\/static.jamasoftware.com\/www\/imports\/2016\/04\/blog-image-chunky-chatty.jpg"},{"@type":"BreadcrumbList","@id":"https:\/\/www.jamasoftware.com\/blog\/2016\/04\/27\/rest-api-design\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.jamasoftware.com\/"},{"@type":"ListItem","position":2,"name":"REST API Design"}]},{"@type":"WebSite","@id":"https:\/\/www.jamasoftware.com\/#website","url":"https:\/\/www.jamasoftware.com\/","name":"Jama Software","description":"Jama Connect\u00ae #1 in Requirements Management","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.jamasoftware.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.jamasoftware.com\/#\/schema\/person\/abe0886b233c2813a679c04066e034b8","name":"Steve Gotsch","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/ed6bf3d28ffe416f991a6120e565840a44526b876780afda309e084ca28cf340?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/ed6bf3d28ffe416f991a6120e565840a44526b876780afda309e084ca28cf340?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ed6bf3d28ffe416f991a6120e565840a44526b876780afda309e084ca28cf340?s=96&d=mm&r=g","caption":"Steve Gotsch"},"description":"Steve Gotsch is an experienced product manager who writes about Jama Software's REST API and how to connect best-in-breed tools across the product development lifecycle.","sameAs":["https:\/\/www.linkedin.com\/in\/steve-gotsch\/"],"url":"https:\/\/www.jamasoftware.com\/blog\/author\/sgotsch\/"}]}},"_links":{"self":[{"href":"https:\/\/www.jamasoftware.com\/legacy\/wp-json\/wp\/v2\/posts\/21025","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jamasoftware.com\/legacy\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jamasoftware.com\/legacy\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jamasoftware.com\/legacy\/wp-json\/wp\/v2\/users\/79"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jamasoftware.com\/legacy\/wp-json\/wp\/v2\/comments?post=21025"}],"version-history":[{"count":0,"href":"https:\/\/www.jamasoftware.com\/legacy\/wp-json\/wp\/v2\/posts\/21025\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.jamasoftware.com\/legacy\/wp-json\/wp\/v2\/media?parent=21025"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jamasoftware.com\/legacy\/wp-json\/wp\/v2\/categories?post=21025"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jamasoftware.com\/legacy\/wp-json\/wp\/v2\/tags?post=21025"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/www.jamasoftware.com\/legacy\/wp-json\/wp\/v2\/industry?post=21025"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}