{"id":13990389,"url":"https://github.com/lambda2/rapis","last_synced_at":"2026-01-18T14:42:48.719Z","repository":{"id":68051163,"uuid":"61573222","full_name":"lambda2/rapis","owner":"lambda2","description":"A specification proposal for API's","archived":false,"fork":false,"pushed_at":"2016-07-05T14:14:11.000Z","size":63,"stargazers_count":54,"open_issues_count":1,"forks_count":10,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-07-22T12:51:35.857Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lambda2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.md","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-20T19:07:03.000Z","updated_at":"2025-02-16T16:42:22.000Z","dependencies_parsed_at":null,"dependency_job_id":"8dfd303f-5b0a-4329-aa05-26c58b4352ec","html_url":"https://github.com/lambda2/rapis","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lambda2/rapis","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambda2%2Frapis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambda2%2Frapis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambda2%2Frapis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambda2%2Frapis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lambda2","download_url":"https://codeload.github.com/lambda2/rapis/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lambda2%2Frapis/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28538294,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T13:04:05.990Z","status":"ssl_error","status_checked_at":"2026-01-18T13:01:44.092Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-09T13:02:39.641Z","updated_at":"2026-01-18T14:42:48.696Z","avatar_url":"https://github.com/lambda2.png","language":null,"funding_links":[],"categories":["Others","Design"],"sub_categories":["Overview"],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cbr\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/lambda2/rapis/master/images/logo.png\" alt=\"RAPIS\" width=\"250\"\u003e\n  \u003cbr\u003e\n  A REST API Standard\n  \u003cbr\u003e\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003eA 21th century way for designing Rest API's\u003c/p\u003e\n\n[![Join the chat at https://gitter.im/lambda2/rapis](https://badges.gitter.im/lambda2/rapis.svg)](https://gitter.im/lambda2/rapis?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\n\u003e This specification is **a possible way** to design a REST API, regardless of the language, format (json, xml, etc...) or used libraries . [If you don't agree on this specifications, there is other ways to structure your REST API !](#5-other-ways-to-structure-your-rest-api). [**All contributions are welcome**, please help me 🙏](#2-please-contribute).\n\n## Table of contents\n\n  1. [Specification](#1-specification)\n    * 1.1 [Design](#11-design)\n    * 1.2 [Formatting](#12-formatting)\n    * 1.3 [Security](#13-security)\n    * 1.4 [Verbs](#14-verbs)\n    * 1.5 [Status codes](#15-status-codes)\n    * 1.6 [Errors](#16-errors)\n    * 1.7 [Parameters](#17-parameters)\n    * 1.8 [Custom HTTP headers](#18-custom-http-headers)\n    * 1.9 [Versioning](#19-versioning)\n    * 1.10 [Pagination](#110-pagination)\n    * 1.11 [Filtering](#111-filtering)\n    * 1.12 [Sorting](#112-sorting)\n    * 1.13 [Searching](#113-searching)\n    * 1.14 [Embedding](#114-embedding)\n    * 1.15 [Selecting](#115-selecting)\n    * 1.16 [Caching](#116-caching)\n    * 1.17 [Asynchronous processing](#117-asynchronous-processing)\n  2. [TODO](#2-todo)\n  3. [Please contribute](#3-please-contribute)\n  4. [Sources and thanks](#4-sources-and-thanks)\n  5. [Other ways to structure your REST API](#5-other-ways-to-structure-your-rest-api)\n\n## 1. Specification\n\n### 1.1 Design\n\nThe API must embrace RESTful design principles. It must be resource-based, and each resource representation must contain enough information to modify or delete the resource on the server, provided it has permission to do so.\n\n- The resources names and fields must be [snake_case](http://en.wikipedia.org/wiki/Snake_case).\n\n  \u003e [snake_case is 20% easier to read than camelCase](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?tp=\u0026arnumber=5521745). That impact on readability would affect API explorability and examples in documentation. \n\n- The resources names must be nouns.\n\n  \u003e [Nouns are good, verbs are bad](http://apigee.com/about/blog/technology/restful-api-design-nouns-are-good-verbs-are-bad)\n\n- The endpoints names must be plural.\n\n  \u003e You don't want to deal with complex pluralization (e.g., foot/feet, child/children, people/people). Keep it simple.\n\n### 1.2 Formatting\n\n- Dates must be returned in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ).\n\n- Geographic coordinates must be returned in `[-]d.d, [-]d.d` format (e.g., 12.3456, -98.7654).\n\n### 1.3 Security\n\n- The API must be served over SSL, using `https`. It must not redirect on non-SSL urls.\n\n  \u003e Always using SSL guaranteed encrypted communications, and allow use of simple access tokens.\n\n### 1.4 Verbs\n\n|       Verb   |                     Description                       |\n|--------------|-------------------------------------------------------|\n|  GET         | Used for retrieving resources.                        |\n|  POST        | Used for creating resources.                          |\n|  PATCH / PUT | Used for updating resources.                          |\n|  DELETE      | Used for deleting resources.                          |\n\n#### Fallback header\n\nThe HTTP client that doesn't support PUT, PATCH or DELETE requests must send a POST request with an `X-HTTP-Method-Override` header specifying the desired verb.\n\nThe server must correctly handle this header. When it is set, it take precedence over the original request method.\n\n#### Location header\n\nWhen a resource is created (with a `POST` request), the response must contain a `Location` header with the link of the new resource.\n\n#### Response on update and create actions\n\nWhen a resource is created or modified (e.g., with a POST, PUT or PATCH request), the response must contain the created or updated representation of the resource.\n\n### 1.5 Status codes\n\n**The API must uses descriptive HTTP response codes to indicate the success or failure of request.**\n\nCodes in the 2xx range must indicate a success, codes in the 4xx range must indicate an error that failed given the information provided (e.g., a required parameter was omitted, a charge failed, etc.), and codes in the 5xx range must indicate a server-side error (e.g., the server is unavailable).\n\nThe server must respond with the following status codes, according to the situation:\n\n|          Http Code        |                               Meaning                                     |\n|---------------------------|---------------------------------------------------------------------------|\n| 200 OK                    | Request succeeded. Response included                                      |\n| 201 Created               | Resource created. URL to new resource in Location header                  |\n| 204 No Content            | Request succeeded, but no response body                                   |\n| 303 See other             | The resource is in another location. See [Asynchronous processing](#asynchronous-processing). |\n| 304 Not Modified          | The response is not modified since the last call. Returned by the cache.  |\n| 400 Bad Request           | Could not parse request                                                   |\n| 401 Unauthorized          | No authentication credentials provided or authentication failed           |\n| 403 Forbidden             | Authenticated user does not have access                                   |\n| 404 Not Found             | Page or resource not found                                                |\n| 405 Method Not Allowed    | The request HTTP method is not allowed for the authenticated user         |\n| 410 Gone                  | The endpoint is no longer available. Useful for old API versions         |\n| 415 Unsupported Media Type| POST/PUT/PATCH request occurred without a application/json content type   |\n| 422 Unprocessable Entry   | A request to modify or create a resource failed due to a validation error |\n| 429 Too Many Requests     | Request rejected due to rate limiting                                     |\n| 500 Internal Server Error | An internal server error occurred                                          |\n| 502 Bad Gateway           | The server was acting as a gateway or proxy and received an invalid response from the upstream server |\n| 503 Service Unavailable   | The server is currently unable to handle the request.                     |\n\n\n### 1.6 Errors\n\n- All errors in the 4xx must return a body containing a `error` key, containing the error code.\n\n- This code must be human readable, and identical over the same kinds of errors.\n\n- The body should also contain a `message` key, containing a more detailed description of the error. \n\n```HTTP\nGET /unicorns/4 HTTP/1.1\n\nHTTP/1.1 404 Not Found\nContent-Type: application/json\n\n{\n   \"error\": \"Not Found\",\n   \"message\": \"Unable to found unicorn with id '4'\"\n}\n```\n\n- On validation errors (with a 422 Unprocessable Entity status code), the body should contain a `messages` array containing all the validation errors.\n\n```HTTP\nPOST /unicorns HTTP/1.1\n\n{\n  \"unicorn\": {\n    \"color\": \"purple\"\n  }\n}\n\nHTTP/1.1 422 Unprocessable Entity\nContent-Type: application/json\n\n{\n   \"error\": \"Validation failed\",\n   \"messages\": [\"name cannot be blank\"]\n}\n```\n\n\n### 1.7 Parameters\n\nResource creation or update parameters must be wrapped in an object as the singular name of the resource.\n\n```HTTP\nPOST /unicorns HTTP/1.1\nAccept: application/json\nContent-Type: application/json\nHost: api.example.com\n\n{\n  \"unicorn\": {\n    \"name\": \"John\",\n    \"color\": \"purple\",\n    \"country_id\": 1\n  }\n}\n\nHTTP/1.1 201 Created\nContent-Type: application/json\n\n{\n  \"unicorn\": {\n    \"id\": 4,\n    \"name\": \"John\",\n    \"color\": \"purple\",\n    \"created_at\": \"2016-07-25T12:19:33Z\"\n  }\n}\n```\n\n\n### 1.8 Custom HTTP headers\n\nAll non-standard HTTP headers must begin by a `X-`.\n\nFor example, for rate limiting, the `X-Rate-Limit-Limit`, `X-Rate-Limit-Remaining` and `X-Rate-Limit-Reset` headers should be used.\n\n### 1.9 Versioning\n\nThe API must be versioned, and must not have breaking changes without version change.\n\n- The client must be able to set the requested version trough the `Accept` header. (e.g., `Accept: application/vnd.myapp.v2+json`).\n  \u003e [This point is very disputed](http://stackoverflow.com/questions/389169/best-practices-for-api-versioning), but we agree on the fact that the URL must describe a resource, and the URL should not contain the versions.\n\n- Without `Accept` header, the API must use the last stable version.\n\n- The response header must contain a `X-Version` field containing the version used for this request.\n\n- The version field should be formated using the [semantic versioning](http://semver.org/).\n\n```HTTP\nGET /unicorns HTTP/1.1\nAccept: application/vnd.example-app.v3.1+json\nContent-Type: application/json\nHost: api.example.org\n\nHTTP/1.1 200 OK\nConnection: keep-alive\nContent-Length: 477\nContent-Type: application/json\nX-Version: 3.1\n\n{\n  [...]\n}\n```\n\n### 1.10 Pagination\n\nRequests for collections should be paginated, and return a limited number of results.\n\nIn this case, the client must be able to change the requested page using the `page[number]` parameter.\n\nThe client should also be able to change the number of items returned per page using the `page[size]` parameter.\n\n\u003e A lot of services uses the `page` and the `per_page` parameters to set the page number and the number of items per page. The server should be able to support both of theses parameters.\n\nA paginated response should have: \n- A [`Link` header](https://tools.ietf.org/html/rfc5988), which should contain links to the next, previous, first and last resources.\n- A `X-Page` header, containing the current page.\n- A `X-Per-Page` header, containing the number of items per page.\n- A `X-Total` header, containing the total items count.\n\n\n```HTTP\nGET /unicorns?page[size]=2 HTTP/1.1\nContent-Type: application/json\nHost: api.example.org\n\nHTTP/1.1 200 OK\nContent-Type: application/json\nLink: \u003chttps://api.example.org/unicorns?page[number]=2\u0026page[size]=2\u003e; rel=\"last\", \u003chttps://api.example.org/unicorns?page[number]=2\u0026page[size]=2\u003e; rel=\"next\"\nX-Page: 1\nX-Per-Page: 2\nX-Total: 4\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"Charles\",\n    \"color\": \"yellow\",\n    \"created_at\": \"2016-07-25T12:19:33Z\"\n  },\n  {\n    \"id\": 2,\n    \"name\": \"Zoe\",\n    \"color\": \"green\",\n    \"created_at\": \"2016-07-25T12:19:33Z\"\n  }\n]\n```\n\n### 1.11 Filtering\n\nThe client should be able to filter resource collections using the `filter` parameter. In this case, only the fields matching the given filter(s) will be returned.\n\nThe value of the `filter` parameter must be a hash of the filter name as a key, and a comma-separated list of the requested values as a value.\n\n```HTTP\nGET /unicorns?filter[color]=yellow HTTP/1.1\nContent-Type: application/json\nHost: api.example.org\n\nHTTP/1.1 200 OK\nContent-Type: application/json\n\n[\n  {\n    \"id\": 1,\n    \"color\": \"yellow\"\n  },\n  {\n    \"id\": 3,\n    \"color\": \"yellow\"\n  }\n]\n```\n\n\n### 1.12 Sorting\n\nThe client should be able to sort resource collections according to one or more fields using the `sort` parameter. The value for `sort` must represent sort fields.\n\nSorting on multiple fields should be done by allowing comma-separated sort fields. In this case, sort fields should be applied in the order specified.\n\nThe sort order for each sort field must be ascending unless it is prefixed with a minus (`-`), in which case it must be descending.\n\n```HTTP\nGET /unicorns?sort=color,-name HTTP/1.1\nContent-Type: application/json\nHost: api.example.org\n\nHTTP/1.1 200 OK\nContent-Type: application/json\n\n[\n  {\n    \"id\": 2,\n    \"name\": \"Zoe\",\n    \"color\": \"green\",\n    \"created_at\": \"2016-07-25T12:19:33Z\"\n  },\n  {\n    \"id\": 4,\n    \"name\": \"John\",\n    \"color\": \"purple\",\n    \"created_at\": \"2016-07-25T12:19:33Z\"\n  },\n  {\n    \"id\": 3,\n    \"name\": \"Mike\",\n    \"color\": \"yellow\",\n    \"created_at\": \"2016-07-25T12:19:33Z\"\n  },\n  {\n    \"id\": 1,\n    \"name\": \"Charles\",\n    \"color\": \"yellow\",\n    \"created_at\": \"2016-07-25T12:19:33Z\"\n  }\n]\n```\n\nIf the server does not support sorting as specified in the query parameter `sort`, it must return a `400 Bad Request` status code.\n\n### 1.13 Searching\n\nThe client should be able to search on resource collections fields using the `search` parameter. In this case, only the fields matching the given search(s) will be returned.\n\nThe value of the `search` parameter must be a hash of the search field as a key, and the query as a value.\n\n```HTTP\nGET /unicorns?search[name]=e HTTP/1.1\nContent-Type: application/json\nHost: api.example.org\n\nHTTP/1.1 200 OK\nContent-Type: application/json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"Charles\",\n    \"color\": \"yellow\",\n    \"created_at\": \"2016-07-25T12:19:33Z\"\n  },\n  {\n    \"id\": 2,\n    \"name\": \"Zoe\",\n    \"color\": \"green\",\n    \"created_at\": \"2016-07-25T12:19:33Z\"\n  },\n  {\n    \"id\": 3,\n    \"name\": \"Mike\",\n    \"color\": \"yellow\",\n    \"created_at\": \"2016-07-25T12:19:33Z\"\n  }\n]\n```\n\nA global search on a resource collection should be implemented using directly a value instead of a hash for the `search` parameter.\n\n### 1.14 Embedding\n\nThe client should be able to include data related to (or referenced) from the resource being requested using the `embed` parameter. The value of the `embed` parameter must be a comma separated list of fields to be embedded. Dot-notation must be used to refer to sub-fields.\n\n```HTTP\nGET /unicorns?embed=country.name HTTP/1.1\nContent-Type: application/json\nHost: api.example.org\n\nHTTP/1.1 200 OK\nContent-Type: application/json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"Charles\",\n    \"color\": \"yellow\",\n    \"created_at\": \"2016-07-25T12:19:33Z\",\n    \"country\": {\n      \"name\": \"Australia\"\n    }\n  },\n  {\n    \"id\": 2,\n    \"name\": \"Zoe\",\n    \"color\": \"green\",\n    \"created_at\": \"2016-07-25T12:19:33Z\",\n    \"country\": {\n      \"name\": \"Italy\"\n    }\n  },\n  {\n    \"id\": 3,\n    \"name\": \"Mike\",\n    \"color\": \"yellow\",\n    \"created_at\": \"2016-07-25T12:19:33Z\",\n    \"country\": {\n      \"name\": \"U.S.A\"\n    }\n  },\n  {\n    \"id\": 4,\n    \"name\": \"John\",\n    \"color\": \"purple\",\n    \"created_at\": \"2016-07-25T12:19:33Z\",\n    \"country\": {\n      \"name\": \"France\"\n    }\n  }\n]\n```\n\n### 1.15 Selecting\n\nThe client should be able to select only specific fields in the response using the `fields` parameter. In this case, only the requested fields will be returned.\n\nThe value of the `fields` parameter must be a hash of the resource name as a key, and a comma-separated list of the fields names to be returned as a value.\n\n```HTTP\nGET /unicorns?fields[unicorns]=id,color HTTP/1.1\nContent-Type: application/json\nHost: api.example.org\n\nHTTP/1.1 200 OK\nContent-Type: application/json\n\n[\n  {\n    \"id\": 1,\n    \"color\": \"yellow\"\n  },\n  {\n    \"id\": 2,\n    \"color\": \"green\"\n  },\n  {\n    \"id\": 3,\n    \"color\": \"yellow\"\n  },\n  {\n    \"id\": 4,\n    \"color\": \"purple\"\n  }\n]\n```\n\nIf the server does not support selection as specified in the query parameter `fields`, it must return a `400 Bad Request` status code.\n\n\n### 1.16 Caching\n\nServer should generate a [ETag header](http://en.wikipedia.org/wiki/HTTP_ETag) containing a hash or checksum of the representation. This value should change whenever the output representation changes.\n\n### 1.17 Asynchronous processing\n\nWhen a resource creation or update is asynchronously processed, the request should return a `202 Accepted` status code with a link in the `Content-Location` header which should redirect to the resource when the job processing is done.\n\n\n```HTTP\nPOST /movies HTTP/1.1\nAccept: application/json\nContent-Type: application/json\nHost: api.example.com\n\n{\n  \"movie\": {\n    \"name\": \"Charlie the Unicorn\",\n    \"source\": \"https://www.youtube.com/watch?v=CsGYh8AacgY\"\n  }\n}\n\nHTTP/1.1 202 Accepted\nContent-Type: application/json\nContent-Location: https://api.example.com/movies/jobs/42\n\n{}\n```\n\nWhen the job process is done, requesting the link in the `Content-Location` header should return a `303 See other` status code with the created resource link in `Location` header.\n\n```HTTP\nGET /movies/jobs/42 HTTP/1.1\nAccept: application/json\n\nHTTP/1.1 303 See other\nContent-Type: application/json\nLocation: https://api.example.com/movies/3\n```\n\n## 2. TODO\n\nThere still a lot to do:\n\n- Create a validator.\n- Define rules about JSON structure.\n- Define rules about performance.\n- Speak more about security (SSL) concerns.\n- Create a more structured way for this guides. Maybe general sections like `basis`, `requests`, `responses` ?\n- Add documentation rules.\n- Add more explanations about technical choices.\n- Translations.\n\n## 3. Please contribute\n\nAll suggestions, questions and ideas are welcome ! You can reach me on [gitter](https://gitter.im/lambda2/rapis), or [fork this project](https://github.com/lambda2/rapis/fork) and make a Pull Request !\n\n## 4. Sources and thanks\n\n- [Nouns are good, verbs are bad](http://apigee.com/about/blog/technology/restful-api-design-nouns-are-good-verbs-are-bad)\n- [Principles of good RESTful API Design](https://codeplanet.io/principles-good-restful-api-design/)\n- [Best Practices for Designing a Pragmatic RESTful API](http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#useful-post-responses)\n- [Semver](http://semver.org/)\n- [JSON API specification](http://jsonapi.org/)\n- [Stackoverflow: Best practices for API versioning?](http://stackoverflow.com/questions/389169/best-practices-for-api-versioning)\n\n## 5. Other ways to structure your REST API\n\nThere is many other specifications. This guide is not intended to be **the one**, it's just a good way, from my point of view and experience, to design a REST API.\n\n- [JSON API](http://jsonapi.org/)\n  \u003e Conventions on JSON API to increase productivity, take advantage of generalized tooling, and focus on what matters: your application.\n\n- [HTTP API DESIGN](https://www.gitbook.com/book/geemus/http-api-design/details)\n  \u003e HTTP API design guide extracted from work on the Heroku Platform API.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flambda2%2Frapis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flambda2%2Frapis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flambda2%2Frapis/lists"}