├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── LANGS.md ├── LICENSE.md ├── README.md ├── en ├── README.md ├── SUMMARY.md ├── artifacts │ ├── README.md │ ├── describe-stability.md │ ├── provide-executable-examples.md │ ├── provide-human-readable-docs.md │ └── provide-machine-readable-json-schema.md ├── foundations │ ├── README.md │ ├── divide-large-responses-across-requests-with-ranges.md │ ├── provide-request-ids-for-introspection.md │ ├── require-secure-connections.md │ ├── require-versioning-in-the-accepts-header.md │ ├── separate-concerns.md │ └── support-etags-for-caching.md ├── requests │ ├── README.md │ ├── accept-serialized-json-in-request-bodies.md │ ├── actions.md │ ├── downcase-paths-and-attributes.md │ ├── minimize-path-nesting.md │ ├── resource-names.md │ ├── support-non-id-dereferencing-for-convenience.md │ └── use-consistent-path-formats.md └── responses │ ├── README.md │ ├── generate-structured-errors.md │ ├── keep-json-minified-in-all-responses.md │ ├── nest-foreign-key-relations.md │ ├── provide-full-resources-where-available.md │ ├── provide-resource-uuids.md │ ├── provide-standard-response-types.md │ ├── provide-standard-timestamps.md │ ├── return-appropriate-status-codes.md │ ├── show-rate-limit-status.md │ └── use-utc-times-formatted-in-iso8601.md └── it ├── README.md └── SUMMARY.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | We welcome contributions to this guide and discussion about its 4 | contents. Please open an issue or pull request on this repository to 5 | propose a change. 6 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | * Andrew Couch 2 | * Ben Hockey 3 | * Brandur 4 | * Brandur 5 | * C. T. Lin 6 | * David Paschich 7 | * Dyego Costa 8 | * Gordon Yeu 9 | * James Manning 10 | * Jonathan Hanson 11 | * Jonathan Roes 12 | * Karl Coelho 13 | * Keith Cirkel 14 | * Mario Vejlupek 15 | * Mark McGranaghan 16 | * Matt Haggard 17 | * Richard Hoberman 18 | * Stefano Uliari 19 | * Steve 20 | * Steven Beeckman 21 | * Thomas Orozco 22 | * Tom Christie 23 | * Travis Paul 24 | * Wesley Beary 25 | * Wesley Beary 26 | * e3 27 | * geemus -------------------------------------------------------------------------------- /LANGS.md: -------------------------------------------------------------------------------- 1 | * [English](en) 2 | * [Italian](it) 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## License 2 | 3 | Copyright the [project contributors](CONTRIBUTORS.md). 4 | 5 | Released under a [Creative Commons Attribution 3.0 Unported License](http://creativecommons.org/licenses/by/3.0/). 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HTTP API Design Guide 2 | 3 | This guide describes a set of HTTP+JSON API design practices, originally 4 | extracted from work on the [Heroku Platform API](https://devcenter.heroku.com/articles/platform-api-reference). 5 | 6 | This guide informs additions to that API and also guides new internal 7 | APIs at Heroku. We hope it’s also of interest to API designers 8 | outside of Heroku. 9 | 10 | Our goals here are consistency and focusing on business logic while 11 | avoiding design bikeshedding. We’re looking for _a good, consistent, 12 | well-documented way_ to design APIs, not necessarily _the only/ideal 13 | way_. 14 | 15 | We assume you’re familiar with the basics of HTTP+JSON APIs and won’t 16 | cover all of the fundamentals of those in this guide. 17 | 18 | Available for online reading and in multiple formats at [gitbook](https://geemus.gitbooks.io/http-api-design). 19 | 20 | We welcome [contributions](https://github.com/interagent/http-api-design/blob/master/CONTRIBUTING.md) to this guide. 21 | 22 | See [Summary](en/SUMMARY.md) for Table of Contents. 23 | 24 | For the best reading experience, we recommend reading via [GitBook](https://geemus.gitbooks.io/http-api-design). 25 | 26 | ### Gitbook Translations 27 | * [English](https://geemus.gitbooks.io/http-api-design/content/en/index.html) 28 | * [Italian](https://geemus.gitbooks.io/http-api-design/content/it/index.html) (based on [f12db3e](https://github.com/interagent/http-api-design/commit/f12db3e)), by [@diegomariani](https://github.com/diegomariani/) 29 | * [Simplified Chinese](https://one-programmer.github.io/docs/http-api-design/) (based on [40d114b](https://github.com/interagent/http-api-design/commit/40d114b6efbc60b84c804dbe7ad34b0d5e155a49)), by [@ZhangBohan](https://github.com/ZhangBohan/) 30 | 31 | ### Git Translations 32 | * [Korean](https://github.com/yoondo/http-api-design) (based on [f38dba6](https://github.com/interagent/http-api-design/commit/f38dba6fd8e2b229ab3f09cd84a8828987188863)), by [@yoondo](https://github.com/yoondo/) 33 | * [Portuguese](https://github.com/Gutem/http-api-design/) (based on [fba98f08b5](https://github.com/interagent/http-api-design/commit/fba98f08b50acbb08b7b30c012a6d0ca795e29ee)), by [@Gutem](https://github.com/Gutem/) 34 | * [Simplified Chinese](https://github.com/ZhangBohan/http-api-design-ZH_CN) (based on [337c4a0](https://github.com/interagent/http-api-design/commit/337c4a05ad08f25c5e232a72638f063925f3228a)), by [@ZhangBohan](https://github.com/ZhangBohan/) 35 | * [Spanish](https://github.com/jmnavarro/http-api-design) (based on [2a74f45](https://github.com/interagent/http-api-design/commit/2a74f45b9afaf6c951352f36c3a4e1b0418ed10b)), by [@jmnavarro](https://github.com/jmnavarro/) 36 | * [Traditional Chinese](https://github.com/kcyeu/http-api-design) (based on [232f8dc](https://github.com/interagent/http-api-design/commit/232f8dc6a941d0b25136bf64998242dae5575f66)), by [@kcyeu](https://github.com/kcyeu/) 37 | * [Turkish](https://github.com/hkulekci/http-api-design/tree/master/tr) (based on [c03842f](https://github.com/interagent/http-api-design/commit/c03842fda80261e82860f6dc7e5ccb2b5d394d51)), by [@hkulekci](https://github.com/hkulekci/) 38 | -------------------------------------------------------------------------------- /en/README.md: -------------------------------------------------------------------------------- 1 | # HTTP API Design Guide 2 | 3 | This guide describes a set of HTTP+JSON API design practices, originally 4 | extracted from work on the [Heroku Platform API](https://devcenter.heroku.com/articles/platform-api-reference). 5 | 6 | This guide informs additions to that API and also guides new internal 7 | APIs at Heroku. We hope it’s also of interest to API designers 8 | outside of Heroku. 9 | 10 | Our goals here are consistency and focusing on business logic while 11 | avoiding design bikeshedding. We’re looking for _a good, consistent, 12 | well-documented way_ to design APIs, not necessarily _the only/ideal 13 | way_. 14 | 15 | We assume you’re familiar with the basics of HTTP+JSON APIs and won’t 16 | cover all of the fundamentals of those in this guide. 17 | 18 | Available for online reading and in multiple formats at [gitbook](https://geemus.gitbooks.io/http-api-design/). 19 | 20 | We welcome [contributions](https://github.com/interagent/http-api-design/blob/master/CONTRIBUTING.md) to this guide. 21 | 22 | See [Summary](https://github.com/interagent/http-api-design/blob/master/en/SUMMARY.md) for Table of Contents. 23 | 24 | ### Translations 25 | * [Portuguese version](https://github.com/Gutem/http-api-design/) (based on [fba98f08b5](https://github.com/interagent/http-api-design/commit/fba98f08b50acbb08b7b30c012a6d0ca795e29ee)), by [@Gutem](https://github.com/Gutem/) 26 | * [Spanish version](https://github.com/jmnavarro/http-api-design) (based on [2a74f45](https://github.com/interagent/http-api-design/commit/2a74f45b9afaf6c951352f36c3a4e1b0418ed10b)), by [@jmnavarro](https://github.com/jmnavarro/) 27 | * [Korean version](https://github.com/yoondo/http-api-design) (based on [f38dba6](https://github.com/interagent/http-api-design/commit/f38dba6fd8e2b229ab3f09cd84a8828987188863)), by [@yoondo](https://github.com/yoondo/) 28 | * [Simplified Chinese version](https://github.com/ZhangBohan/http-api-design-ZH_CN) (based on [337c4a0](https://github.com/interagent/http-api-design/commit/337c4a05ad08f25c5e232a72638f063925f3228a)), by [@ZhangBohan](https://github.com/ZhangBohan/) 29 | * [Traditional Chinese version](https://github.com/kcyeu/http-api-design) (based on [232f8dc](https://github.com/interagent/http-api-design/commit/232f8dc6a941d0b25136bf64998242dae5575f66)), by [@kcyeu](https://github.com/kcyeu/) 30 | * [Turkish version](https://github.com/hkulekci/http-api-design/tree/master/tr) (based on [c03842f](https://github.com/interagent/http-api-design/commit/c03842fda80261e82860f6dc7e5ccb2b5d394d51)), by [@hkulekci](https://github.com/hkulekci/) 31 | 32 | -------------------------------------------------------------------------------- /en/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # HTTP API Design Guide 2 | 3 | * [Foundations](foundations/README.md) 4 | * [Separate Concerns](foundations/separate-concerns.md) 5 | * [Require Secure Connections](foundations/require-secure-connections.md) 6 | * [Require Versioning in the Accepts Header](foundations/require-versioning-in-the-accepts-header.md) 7 | * [Support ETags for Caching](foundations/support-etags-for-caching.md) 8 | * [Provide Request-Ids for Introspection](foundations/provide-request-ids-for-introspection.md) 9 | * [Divide Large Responses Across Requests with Ranges](foundations/divide-large-responses-across-requests-with-ranges.md) 10 | * [Requests](requests/README.md) 11 | * [Accept serialized JSON in request bodies](requests/accept-serialized-json-in-request-bodies.md) 12 | * [Resource names](requests/resource-names.md) 13 | * [Actions](requests/actions.md) 14 | * [Use consistent path formats](requests/use-consistent-path-formats.md) 15 | * [Downcase paths and attributes](requests/downcase-paths-and-attributes.md) 16 | * [Support non-id dereferencing for convenience](requests/support-non-id-dereferencing-for-convenience.md) 17 | * [Minimize path nesting](requests/minimize-path-nesting.md) 18 | * [Responses](responses/README.md) 19 | * [Return appropriate status codes](responses/return-appropriate-status-codes.md) 20 | * [Provide full resources where available](responses/provide-full-resources-where-available.md) 21 | * [Provide resource (UU)IDs](responses/provide-resource-uuids.md) 22 | * [Provide standard timestamps](responses/provide-standard-timestamps.md) 23 | * [Provide standard response types](responses/provide-standard-response-types.md) 24 | * [Use UTC times formatted in ISO8601](responses/use-utc-times-formatted-in-iso8601.md) 25 | * [Nest foreign key relations](responses/nest-foreign-key-relations.md) 26 | * [Generate structured errors](responses/generate-structured-errors.md) 27 | * [Show rate limit status](responses/show-rate-limit-status.md) 28 | * [Keep JSON minified in all responses](responses/keep-json-minified-in-all-responses.md) 29 | * [Artifacts](artifacts/README.md) 30 | * [Provide machine-readable JSON schema](artifacts/provide-machine-readable-json-schema.md) 31 | * [Provide human-readable docs](artifacts/provide-human-readable-docs.md) 32 | * [Provide executable examples](artifacts/provide-executable-examples.md) 33 | * [Describe stability](artifacts/describe-stability.md) 34 | -------------------------------------------------------------------------------- /en/artifacts/README.md: -------------------------------------------------------------------------------- 1 | ### Artifacts 2 | 3 | The Artifacts section describes the physical objects we use to manage and 4 | discuss API designs and patterns. 5 | -------------------------------------------------------------------------------- /en/artifacts/describe-stability.md: -------------------------------------------------------------------------------- 1 | #### Describe stability 2 | 3 | Describe the stability of your API or its various endpoints according to 4 | its maturity and stability, e.g. with prototype/development/production 5 | flags. 6 | 7 | See the [Heroku API compatibility policy](https://devcenter.heroku.com/articles/api-compatibility-policy) 8 | for a possible stability and change management approach. 9 | 10 | Once your API is declared production-ready and stable, do not make 11 | backwards incompatible changes within that API version. If you need to 12 | make backwards-incompatible changes, create a new API with an 13 | incremented version number. 14 | -------------------------------------------------------------------------------- /en/artifacts/provide-executable-examples.md: -------------------------------------------------------------------------------- 1 | #### Provide executable examples 2 | 3 | Provide executable examples that users can type directly into their 4 | terminals to see working API calls. To the greatest extent possible, 5 | these examples should be usable verbatim, to minimize the amount of 6 | work a user needs to do to try the API, e.g.: 7 | 8 | ```bash 9 | $ export TOKEN=... # acquire from dashboard 10 | $ curl -is https://$TOKEN@service.com/users 11 | ``` 12 | 13 | If you use [prmd](https://github.com/interagent/prmd) to generate Markdown 14 | docs, you will get examples for each endpoint for free. 15 | -------------------------------------------------------------------------------- /en/artifacts/provide-human-readable-docs.md: -------------------------------------------------------------------------------- 1 | #### Provide human-readable docs 2 | 3 | Provide human-readable documentation that client developers can use to 4 | understand your API. 5 | 6 | If you create a schema with prmd as described above, you can easily 7 | generate Markdown docs for all endpoints with `prmd doc`. 8 | 9 | In addition to endpoint details, provide an API overview with 10 | information about: 11 | 12 | * Authentication, including acquiring and using authentication tokens. 13 | * API stability and versioning, including how to select the desired API 14 | version. 15 | * Common request and response headers. 16 | * Error serialization format. 17 | * Examples of using the API with clients in different languages. 18 | -------------------------------------------------------------------------------- /en/artifacts/provide-machine-readable-json-schema.md: -------------------------------------------------------------------------------- 1 | #### Provide machine-readable JSON schema 2 | 3 | Provide a machine-readable schema to exactly specify your API. Use 4 | [prmd](https://github.com/interagent/prmd) to manage your schema, and ensure 5 | it validates with `prmd verify`. 6 | -------------------------------------------------------------------------------- /en/foundations/README.md: -------------------------------------------------------------------------------- 1 | ### Foundations 2 | 3 | The Foundations section outlines the design principles upon which the rest of 4 | the guide builds. 5 | -------------------------------------------------------------------------------- /en/foundations/divide-large-responses-across-requests-with-ranges.md: -------------------------------------------------------------------------------- 1 | #### Divide Large Responses Across Requests with Ranges 2 | 3 | Large responses should be broken across multiple requests using `Range` headers 4 | to specify when more data is available and how to retrieve it. See the 5 | [Heroku Platform API discussion of Ranges](https://devcenter.heroku.com/articles/platform-api-reference#ranges) 6 | for the details of request and response headers, status codes, limits, 7 | ordering, and iteration. 8 | -------------------------------------------------------------------------------- /en/foundations/provide-request-ids-for-introspection.md: -------------------------------------------------------------------------------- 1 | #### Provide Request-Ids for Introspection 2 | 3 | Include a `Request-Id` header in each API response, populated with a 4 | UUID value. By logging these values on the client, server and any backing 5 | services, it provides a mechanism to trace, diagnose and debug requests. 6 | -------------------------------------------------------------------------------- /en/foundations/require-secure-connections.md: -------------------------------------------------------------------------------- 1 | #### Require Secure Connections 2 | 3 | Require secure connections with TLS to access the API, without exception. 4 | It’s not worth trying to figure out or explain when it is OK to use TLS 5 | and when it’s not. Just require TLS for everything. 6 | 7 | Ideally, simply reject any non-TLS requests by not responding to requests for 8 | http or port 80 to avoid any insecure data exchange. In environments where this 9 | is not possible, respond with `403 Forbidden`. 10 | 11 | Redirects are discouraged since they allow sloppy/bad client behaviour without 12 | providing any clear gain. Clients that rely on redirects double up on 13 | server traffic and render TLS useless since sensitive data will already 14 | have been exposed during the first call. 15 | -------------------------------------------------------------------------------- /en/foundations/require-versioning-in-the-accepts-header.md: -------------------------------------------------------------------------------- 1 | #### Require Versioning in the Accepts Header 2 | 3 | Versioning and the transition between versions can be one of the more 4 | challenging aspects of designing and operating an API. As such, it is best to 5 | start with some mechanisms in place to mitigate this from the start. 6 | 7 | To prevent surprise, breaking changes to users, it is best to require a version 8 | be specified with all requests. Default versions should be avoided as they are 9 | very difficult, at best, to change in the future. 10 | 11 | It is best to provide version specification in the headers, with other 12 | metadata, using the `Accept` header with a custom content type, e.g.: 13 | 14 | ``` 15 | Accept: application/vnd.heroku+json; version=3 16 | ``` 17 | -------------------------------------------------------------------------------- /en/foundations/separate-concerns.md: -------------------------------------------------------------------------------- 1 | #### Separate Concerns 2 | 3 | Keep things simple while designing by separating the concerns between the 4 | different parts of the request and response cycle. Keeping simple rules here 5 | allows for greater focus on larger and harder problems. 6 | 7 | Requests and responses will be made to address a particular resource or 8 | collection. Use the path to indicate identity, the body to transfer the 9 | contents and headers to communicate metadata. Query params may be used as a 10 | means to pass header information also in edge cases, but headers are preferred 11 | as they are more flexible and can convey more diverse information. 12 | -------------------------------------------------------------------------------- /en/foundations/support-etags-for-caching.md: -------------------------------------------------------------------------------- 1 | #### Support ETags for Caching 2 | 3 | Include an `ETag` header in all responses, identifying the specific 4 | version of the returned resource. This allows users to cache resources 5 | and use requests with this value in the `If-None-Match` header to determine 6 | if the cache should be updated. 7 | -------------------------------------------------------------------------------- /en/requests/README.md: -------------------------------------------------------------------------------- 1 | ### Requests 2 | 3 | The Requests section provides an overview of patterns for API requests. 4 | -------------------------------------------------------------------------------- /en/requests/accept-serialized-json-in-request-bodies.md: -------------------------------------------------------------------------------- 1 | #### Accept serialized JSON in request bodies 2 | 3 | Accept serialized JSON on `PUT`/`PATCH`/`POST` request bodies, either 4 | instead of or in addition to form-encoded data. This creates symmetry 5 | with JSON-serialized response bodies, e.g.: 6 | 7 | ```bash 8 | $ curl -X POST https://service.com/apps \ 9 | -H "Content-Type: application/json" \ 10 | -d '{"name": "demoapp"}' 11 | 12 | { 13 | "id": "01234567-89ab-cdef-0123-456789abcdef", 14 | "name": "demoapp", 15 | "owner": { 16 | "email": "username@example.com", 17 | "id": "01234567-89ab-cdef-0123-456789abcdef" 18 | }, 19 | ... 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /en/requests/actions.md: -------------------------------------------------------------------------------- 1 | ##### Actions 2 | 3 | Prefer endpoint configurations that don’t require special actions. In cases 4 | where actions are needed, clearly delineate them with the `actions` prefix: 5 | 6 | ``` 7 | /resources/:resource/actions/:action 8 | ``` 9 | 10 | e.g. to stop a particular run: 11 | 12 | ``` 13 | /runs/{run_id}/actions/stop 14 | ``` 15 | 16 | Actions on collections should also be minimized. Where needed, they should use 17 | a top-level actions delineation to avoid namespace conflicts and clearly show 18 | the scope of action: 19 | 20 | ``` 21 | /actions/:action/resources 22 | ``` 23 | 24 | e.g. to restart all servers: 25 | 26 | ``` 27 | /actions/restart/servers 28 | ``` 29 | -------------------------------------------------------------------------------- /en/requests/downcase-paths-and-attributes.md: -------------------------------------------------------------------------------- 1 | #### Downcase paths and attributes 2 | 3 | Use downcased and dash-separated path names, for alignment with 4 | hostnames, e.g: 5 | 6 | ``` 7 | service-api.com/users 8 | service-api.com/app-setups 9 | ``` 10 | 11 | Downcase attributes as well, but use underscore separators so that 12 | attribute names can be typed without quotes in JavaScript, e.g.: 13 | 14 | ``` 15 | service_class: "first" 16 | ``` 17 | -------------------------------------------------------------------------------- /en/requests/minimize-path-nesting.md: -------------------------------------------------------------------------------- 1 | #### Minimize path nesting 2 | 3 | In data models with nested parent/child resource relationships, paths 4 | may become deeply nested, e.g.: 5 | 6 | ``` 7 | /orgs/{org_id}/apps/{app_id}/dynos/{dyno_id} 8 | ``` 9 | 10 | Limit nesting depth by preferring to locate resources at the root 11 | path. Use nesting to indicate scoped collections. For example, for the 12 | case above where a dyno belongs to an app belongs to an org: 13 | 14 | ``` 15 | /orgs/{org_id} 16 | /orgs/{org_id}/apps 17 | /apps/{app_id} 18 | /apps/{app_id}/dynos 19 | /dynos/{dyno_id} 20 | ``` 21 | -------------------------------------------------------------------------------- /en/requests/resource-names.md: -------------------------------------------------------------------------------- 1 | ##### Resource names 2 | 3 | Use the plural version of a resource name unless the resource in question is a singleton within the system (for example, the overall status of the system might be `/status`). This keeps it consistent in the way you refer to particular resources. 4 | -------------------------------------------------------------------------------- /en/requests/support-non-id-dereferencing-for-convenience.md: -------------------------------------------------------------------------------- 1 | #### Support non-id dereferencing for convenience 2 | 3 | In some cases it may be inconvenient for end-users to provide IDs to 4 | identify a resource. For example, a user may think in terms of a Heroku 5 | app name, but that app may be identified by a UUID. In these cases you 6 | may want to accept both an id or name, e.g.: 7 | 8 | ```bash 9 | $ curl https://service.com/apps/{app_id_or_name} 10 | $ curl https://service.com/apps/97addcf0-c182 11 | $ curl https://service.com/apps/www-prod 12 | ``` 13 | 14 | Do not accept only names to the exclusion of IDs. 15 | -------------------------------------------------------------------------------- /en/requests/use-consistent-path-formats.md: -------------------------------------------------------------------------------- 1 | #### Use consistent path formats 2 | -------------------------------------------------------------------------------- /en/responses/README.md: -------------------------------------------------------------------------------- 1 | ### Responses 2 | 3 | The Responses section provides an overview of patterns for API responses. 4 | -------------------------------------------------------------------------------- /en/responses/generate-structured-errors.md: -------------------------------------------------------------------------------- 1 | #### Generate structured errors 2 | 3 | Generate consistent, structured response bodies on errors. Include a 4 | machine-readable error `id`, a human-readable error `message`, and 5 | optionally a `url` pointing the client to further information about the 6 | error and how to resolve it, e.g.: 7 | 8 | ``` 9 | HTTP/1.1 429 Too Many Requests 10 | ``` 11 | 12 | ```json 13 | { 14 | "id": "rate_limit", 15 | "message": "Account reached its API rate limit.", 16 | "url": "https://docs.service.com/rate-limits" 17 | } 18 | ``` 19 | 20 | Document your error format and the possible error `id`s that clients may 21 | encounter. 22 | -------------------------------------------------------------------------------- /en/responses/keep-json-minified-in-all-responses.md: -------------------------------------------------------------------------------- 1 | #### Keep JSON minified in all responses 2 | 3 | Extra whitespace adds needless response size to requests, and many 4 | clients for human consumption will automatically "prettify" JSON 5 | output. It is best to keep JSON responses minified e.g.: 6 | 7 | ```json 8 | {"beta":false,"email":"alice@heroku.com","id":"01234567-89ab-cdef-0123-456789abcdef","last_login":"2012-01-01T12:00:00Z","created_at":"2012-01-01T12:00:00Z","updated_at":"2012-01-01T12:00:00Z"} 9 | ``` 10 | 11 | Instead of e.g.: 12 | 13 | ```json 14 | { 15 | "beta": false, 16 | "email": "alice@heroku.com", 17 | "id": "01234567-89ab-cdef-0123-456789abcdef", 18 | "last_login": "2012-01-01T12:00:00Z", 19 | "created_at": "2012-01-01T12:00:00Z", 20 | "updated_at": "2012-01-01T12:00:00Z" 21 | } 22 | ``` 23 | 24 | You may consider optionally providing a way for clients to retrieve 25 | more verbose response, either via a query parameter (e.g. `?pretty=true`) 26 | or via an `Accept` header param (e.g. 27 | `Accept: application/vnd.heroku+json; version=3; indent=4;`). 28 | -------------------------------------------------------------------------------- /en/responses/nest-foreign-key-relations.md: -------------------------------------------------------------------------------- 1 | #### Nest foreign key relations 2 | 3 | Serialize foreign key references with a nested object, e.g.: 4 | 5 | ```javascript 6 | { 7 | "name": "service-production", 8 | "owner": { 9 | "id": "5d8201b0..." 10 | }, 11 | // ... 12 | } 13 | ``` 14 | 15 | Instead of e.g.: 16 | 17 | ```javascript 18 | { 19 | "name": "service-production", 20 | "owner_id": "5d8201b0...", 21 | // ... 22 | } 23 | ``` 24 | 25 | This approach makes it possible to inline more information about the 26 | related resource without having to change the structure of the response 27 | or introduce more top-level response fields, e.g.: 28 | 29 | ```javascript 30 | { 31 | "name": "service-production", 32 | "owner": { 33 | "id": "5d8201b0...", 34 | "email": "alice@heroku.com" 35 | }, 36 | // ... 37 | } 38 | ``` 39 | 40 | When nesting foreign key relations, use either the full record or just the foreign keys. Providing a subset of fields can lead to surprises and confusion, makes inconsistencies between different actions and endpoints more likely. 41 | 42 | To avoid inconsistency and confusion, serialize either: 43 | - **foreign keys** only - values the full record can be looked up with, like `id`, `slug`, `email`. 44 | - **full record**, all fields (this would be an "embedded record") 45 | -------------------------------------------------------------------------------- /en/responses/provide-full-resources-where-available.md: -------------------------------------------------------------------------------- 1 | #### Provide full resources where available 2 | 3 | Provide the full resource representation (i.e. the object with all 4 | attributes) whenever possible in the response. Always provide the full 5 | resource on 200 and 201 responses, including `PUT`/`PATCH` and `DELETE` 6 | requests, e.g.: 7 | 8 | ```bash 9 | $ curl -X DELETE \ 10 | https://service.com/apps/1f9b/domains/0fd4 11 | 12 | HTTP/1.1 200 OK 13 | Content-Type: application/json;charset=utf-8 14 | ... 15 | { 16 | "created_at": "2012-01-01T12:00:00Z", 17 | "hostname": "subdomain.example.com", 18 | "id": "01234567-89ab-cdef-0123-456789abcdef", 19 | "updated_at": "2012-01-01T12:00:00Z" 20 | } 21 | ``` 22 | 23 | 202 responses will not include the full resource representation, 24 | e.g.: 25 | 26 | ```bash 27 | $ curl -X DELETE \ 28 | https://service.com/apps/1f9b/dynos/05bd 29 | 30 | HTTP/1.1 202 Accepted 31 | Content-Type: application/json;charset=utf-8 32 | ... 33 | {} 34 | ``` 35 | -------------------------------------------------------------------------------- /en/responses/provide-resource-uuids.md: -------------------------------------------------------------------------------- 1 | #### Provide resource (UU)IDs 2 | 3 | Give each resource an `id` attribute by default. Use UUIDs unless you 4 | have a very good reason not to. Don’t use IDs that won’t be globally 5 | unique across instances of the service or other resources in the 6 | service, especially auto-incrementing IDs. 7 | 8 | Render UUIDs in downcased `8-4-4-4-12` format, e.g.: 9 | 10 | ``` 11 | "id": "01234567-89ab-cdef-0123-456789abcdef" 12 | ``` 13 | -------------------------------------------------------------------------------- /en/responses/provide-standard-response-types.md: -------------------------------------------------------------------------------- 1 | #### Provide standard response types 2 | 3 | This document describes the acceptable values for each of JSON's basic data 4 | types. 5 | 6 | ### String 7 | 8 | * Acceptable values: 9 | * string 10 | * `null` 11 | 12 | e.g: 13 | 14 | ```javascript 15 | [ 16 | { 17 | "description": "very descriptive description." 18 | }, 19 | { 20 | "description": null 21 | }, 22 | ] 23 | ``` 24 | 25 | ### Boolean 26 | 27 | * Acceptable values: 28 | * true 29 | * false 30 | 31 | e.g: 32 | 33 | ```javascript 34 | [ 35 | { 36 | "provisioned_licenses": true 37 | }, 38 | { 39 | "provisioned_licenses": false 40 | }, 41 | ] 42 | ``` 43 | 44 | ### Number 45 | 46 | * Acceptable values: 47 | * number 48 | * `null` 49 | 50 | Note: some JSON parsers will return numbers with a precision of over 15 51 | decimal places as strings. If you need precision greater than 15 decimals, 52 | always return a string for that value. If not, convert those strings to numbers 53 | so that consumers of the API always know what value type to expect. 54 | 55 | e.g: 56 | 57 | ```javascript 58 | [ 59 | { 60 | "average": 27.123 61 | }, 62 | { 63 | "average": 12.123456789012 64 | }, 65 | ] 66 | ``` 67 | 68 | ### Array 69 | 70 | * Acceptable values: 71 | * array 72 | 73 | Note: Return an empty array rather than `NULL` when there are no values in the 74 | array. 75 | 76 | e.g: 77 | 78 | ```javascript 79 | [ 80 | { 81 | "child_ids": [1, 2, 3, 4], 82 | }, 83 | { 84 | "child_ids": [], 85 | } 86 | ] 87 | ``` 88 | 89 | ### Object 90 | 91 | * Acceptable values: 92 | * object 93 | * null 94 | 95 | e.g: 96 | 97 | ```javascript 98 | [ 99 | { 100 | "name": "service-production", 101 | "owner": { 102 | "id": "5d8201b0..." 103 | } 104 | }, 105 | { 106 | "name": "service-staging", 107 | "owner": null 108 | } 109 | ] 110 | ``` 111 | -------------------------------------------------------------------------------- /en/responses/provide-standard-timestamps.md: -------------------------------------------------------------------------------- 1 | #### Provide standard timestamps 2 | 3 | Provide `created_at` and `updated_at` timestamps for resources by default, 4 | e.g: 5 | 6 | ```javascript 7 | { 8 | // ... 9 | "created_at": "2012-01-01T12:00:00Z", 10 | "updated_at": "2012-01-01T13:00:00Z", 11 | // ... 12 | } 13 | ``` 14 | 15 | These timestamps may not make sense for some resources, in which case 16 | they can be omitted. 17 | -------------------------------------------------------------------------------- /en/responses/return-appropriate-status-codes.md: -------------------------------------------------------------------------------- 1 | #### Return appropriate status codes 2 | 3 | Return appropriate HTTP status codes with each response. Successful 4 | responses should be coded according to this guide: 5 | 6 | * `200`: Request succeeded for a `GET`, `POST`, `DELETE`, or `PATCH` call that 7 | completed synchronously, or a `PUT` call that synchronously updated an 8 | existing resource 9 | * `201`: Request succeeded for a `POST`, or `PUT` call that synchronously 10 | created a new resource. It is also best practice to provide a 'Location' 11 | header pointing to the newly created resource. This is particularly useful 12 | in the `POST` context as the new resource will have a different URL than the 13 | original request. 14 | * `202`: Request accepted for a `POST`, `PUT`, `DELETE`, or `PATCH` call that 15 | will be processed asynchronously 16 | * `206`: Request succeeded on `GET`, but only a partial response 17 | returned: see [above on ranges](../foundations/divide-large-responses-across-requests-with-ranges.md) 18 | 19 | Pay attention to the use of authentication and authorization error codes: 20 | 21 | * `401 Unauthorized`: Request failed because user is not authenticated 22 | * `403 Forbidden`: Request failed because user does not have authorization to access a specific resource 23 | 24 | Return suitable codes to provide additional information when there are errors: 25 | 26 | * `422 Unprocessable Entity`: Your request was understood, but contained invalid parameters 27 | * `429 Too Many Requests`: You have been rate-limited, retry later 28 | * `500 Internal Server Error`: Something went wrong on the server, check status site and/or report the issue 29 | 30 | Refer to the [HTTP response code spec](https://tools.ietf.org/html/rfc7231#section-6) 31 | for guidance on status codes for user error and server error cases. 32 | -------------------------------------------------------------------------------- /en/responses/show-rate-limit-status.md: -------------------------------------------------------------------------------- 1 | #### Show rate limit status 2 | 3 | Rate limit requests from clients to protect the health of the service 4 | and maintain high service quality for other clients. You can use a 5 | [token bucket algorithm](http://en.wikipedia.org/wiki/Token_bucket) to 6 | quantify request limits. 7 | 8 | Return the remaining number of request tokens with each request in the 9 | `RateLimit-Remaining` response header. 10 | -------------------------------------------------------------------------------- /en/responses/use-utc-times-formatted-in-iso8601.md: -------------------------------------------------------------------------------- 1 | #### Use UTC times formatted in ISO8601 2 | 3 | Accept and return times in UTC only. Render times in ISO8601 format, 4 | e.g.: 5 | 6 | ``` 7 | "finished_at": "2012-01-01T12:00:00Z" 8 | ``` 9 | -------------------------------------------------------------------------------- /it/README.md: -------------------------------------------------------------------------------- 1 | # Guida alla progettazione di API HTTP 2 | 3 | Questa guida descrive un insieme di pratiche per la progettazione di API HTTP+JSON, originariamente tratte dal lavoro sulle [API della Piattaforma Heroku](https://devcenter.heroku.com/articles/platform-api-reference). 4 | 5 | La guida serve come riferimento sia per le modifiche alle API correnti che per lo sviluppo di nuove API all'interno di Heroku; speriamo sia di interesse per tutti gli API designer anche al di fuori di Heroku. 6 | 7 | I nostri obiettivi sono la coerenza ed il focalizzarsi sulla logica di business, evitando inutili perdite di tempo durante la progettazione. Perseguiamo un _metodo ottimale, coerente e ben documentato_ per progettare API, che non sia necessariamente _l'unico e solo modo ideale_ di farlo. 8 | 9 | Diamo per scontato che tu abbia già familiarità con i principi alla base delle API HTTP+JSON, quindi questa guida non comprende tutta la parte teorica fondamentale sull'argomento. 10 | 11 | La guida è disponibile in diversi formati a questo link [gitbook](https://www.gitbook.com/read/book/geemus/http-api-design) 12 | 13 | Accettiamo volentieri [contributi](../CONTRIBUTING.md) alla guida. 14 | 15 | Vai al [Sommario](SUMMARY.md) per l'indice dei contenuti. 16 | 17 | ### Traduzioni 18 | * [Versione in Portoghese](https://github.com/Gutem/http-api-design/) (based on [fba98f08b5](https://github.com/interagent/http-api-design/commit/fba98f08b50acbb08b7b30c012a6d0ca795e29ee)), di [@Gutem](https://github.com/Gutem/) 19 | * [Versione in Spagnolo](https://github.com/jmnavarro/http-api-design) (based on [2a74f45](https://github.com/interagent/http-api-design/commit/2a74f45b9afaf6c951352f36c3a4e1b0418ed10b)), di [@jmnavarro](https://github.com/jmnavarro/) 20 | * [Versione in Coreano](https://github.com/yoondo/http-api-design) (based on [f38dba6](https://github.com/interagent/http-api-design/commit/f38dba6fd8e2b229ab3f09cd84a8828987188863)), di [@yoondo](https://github.com/yoondo/) 21 | * [Versione in Cinese Semplificato](https://github.com/ZhangBohan/http-api-design-ZH_CN) (based on [337c4a0](https://github.com/interagent/http-api-design/commit/337c4a05ad08f25c5e232a72638f063925f3228a)), di [@ZhangBohan](https://github.com/ZhangBohan/) 22 | * [Versione in Cinese Tradizionale](https://github.com/kcyeu/http-api-design) (based on [232f8dc](https://github.com/interagent/http-api-design/commit/232f8dc6a941d0b25136bf64998242dae5575f66)), di [@kcyeu](https://github.com/kcyeu/) 23 | * [Versione in Turco](https://github.com/hkulekci/http-api-design/tree/master/tr) (based on [c03842f](https://github.com/interagent/http-api-design/commit/c03842fda80261e82860f6dc7e5ccb2b5d394d51)), di [@hkulekci](https://github.com/hkulekci/) 24 | 25 | -------------------------------------------------------------------------------- /it/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Guida alla progettazione delle API HTTP 2 | 3 | * [Fondamenti](SUMMARY.md#fondamenti) 4 | * [Concetti separati](SUMMARY.md#concetti-separati) 5 | * [Utlizza una connessione sicura (TLS)](SUMMARY.md#utlizza-una-connessione-sicura-(tls)) 6 | * [Richiedi il versioning negli Accept Headers](SUMMARY.md#richiedi-il-versioning-negli-accept-headers) 7 | * [Supporta ETag per il caching](SUMMARY.md#supporta-etag-per-il-caching) 8 | * [Fornisci un parametro Request-Ids per l'analisi](SUMMARY.md#fornisci-un-parametro-request-ids-per-lanalisi) 9 | * [Dividi risposte molto lunghe in piu richieste con range](SUMMARY.md#dividi-risposte-molto-lunghe-in-piu-richieste-con-range) 10 | * [Richieste](SUMMARY.md#richieste) 11 | * [Accetta JSON serializzato nei corpi delle richieste](SUMMARY.md#accetta-json-serializzato-nei-corpi-delle-richieste) 12 | * [Nomi delle risorse](SUMMARY.md#nomi-delle-risorse) 13 | * [Azioni](SUMMARY.md#azioni) 14 | * [Usa un formato consistente per i percorsi (path)](SUMMARY.md#usa-un-formato-consistente-per-i-percorsi-path) 15 | * [Caratteri minuscoli per percorsi e attributi](SUMMARY.md#caratteri-minuscoli-per-percorsi-e-attributi) 16 | * [Supporta anche riferimenti non-id per comodita](SUMMARY.md#supporta-anche-riferimenti-non-id-per-comodita) 17 | * [Minimizza annidamento dei percorsi](SUMMARY.md#minimizza-annidamento-dei-percorsi) 18 | * [Risposte](SUMMARY.md#risposte) 19 | * [Ritorna sempre un codice di stato appropriato](SUMMARY.md#ritorna-sempre-un-codice-di-stato-appropriato) 20 | * [Fornisci le risorse interamente, quando possibile](SUMMARY.md#fornisci-le-risorse-interamente-quando-possibile) 21 | * [Fornisci gli (UU)IDs delle risorse](SUMMARY.md#fornisci-gli-uuids-delle-risorse) 22 | * [Fornisci dei timestamps standard](SUMMARY.md#fornisci-dei-timestamps-standard) 23 | * [Usa date in formato UTC formattate in ISO8601](SUMMARY.md#usa-date-in-formato-utc-formattate-in-iso8601) 24 | * [Annida relazioni tramite le chiavi esterne (foreign-key)](SUMMARY.md#annida-relazioni-tramite-le-chiavi-esterne-foreign-key) 25 | * [Genera errori strutturati](SUMMARY.md#genera-errori-strutturati) 26 | * [Visualizza lo stato del limite delle richieste](SUMMARY.md#visualizza-lo-stato-del-limite-delle-richieste) 27 | * [Mantieni il JSON minimizzato in tutte le risposte](SUMMARY.md#mantieni-il-json-minimizzato-in-tutte-le-risposte) 28 | * [Artefatti](SUMMARY.md#artefatti) 29 | * [Fornisci uno schema JSON interpretabile](SUMMARY.md#fornisci-uno-schema-json-interpretabile) 30 | * [Fornisci una documentazione comprensibile allo sviluppatore](SUMMARY.md#fornisci-una-documentazione-comprensibile-allo-sviluppatore) 31 | * [Fornisci degli esempi](SUMMARY.md#fornisci-degli-esempi) 32 | * [Specifica la stabilità della tua API](SUMMARY.md#specifica-la-stabilita-della-tua-api) 33 | 34 | ### Fondamenti 35 | 36 | Questa sezione illustra i principi di progettazione, sui quali si basa questa guida 37 | 38 | 39 | #### Concetti separati 40 | 41 | Struttura i componenti in maniera semplice mentre li progetti, separando i concetti tra le varie parti del ciclo di richiesta e risposta. Mantenendo la semplicita sui componenti, avrai possibilità di focalizzarti di più su problemi più grandi e più difficili da risolvere. 42 | 43 | La richiesta e la risposta saranno fatte in modo da gestire una particolare risorsa oppure una loro collezione. Usa il percorso (path) per indicare un'identità, il body per trasferire il contenuto e gli headers per comunicare dati aggiuntivi (metadata). I parametri di query passati nell'url, possono essere usati come alternativa agli headers, solo in rari casi. Gli headers sono sempre preferiti, perche permettono più flessibilità e permettono di inviare informazioni più dettagliate. 44 | 45 | #### Utlizza una connessione sicura (TLS) 46 | 47 | Richiedi una connessione sicura con protocollo TLS per accedere alle APIs, senza eccezioni. 48 | Non importa cercare di capire quando è opportuno usare TLS oppure quando non lo è. Semplicemente richiedila sempre. 49 | 50 | Idealmente, puoi rifiutare qualsiasi richiesta che non sia fatta utilizzando il protocollo TLS, per evitare scambi di dati ed informazioni non sicuri. Nel caso in cui non possa gestire questo tipo di regola, basta rispondere con un `403 Forbidden`. 51 | 52 | I redirects sono sconsigliati in quanto non rappresentano un buon approccio. I clients che si imbattono in molti redirects, raddoppiano il traffico sul server e rendono pressocche inutile il protocollo TLS, in quanto le informazioni sensibili vengono esplicitate durante la prima chiamata http 53 | 54 | #### Richiedi il versioning negli Accept Headers 55 | 56 | Un sistema di versioning e transizione tra le versioni può essere uno degli aspetti più difficili da progettare e realizzare nelle tue REST API. Proprio per questo, è meglio cominciare con alcuni accorgimenti che ci aiuteranno a mitigare questo tipo di problemi sin da subito. 57 | 58 | Per evitare sorprese, cambiamenti bruschi agli utenti, è certamente buona norma richiedere di specificare la versione delle APIs in tutte le richieste. Il meccanismo di impostare una versione di default dovrebbe essere evitato, in quanto è molto difficile da cambiare in futuro. 59 | 60 | L'approccio migliore sarebbe quello di specificare la versione negli headers http, con altri metadata, utilizzando per esempio `Accept` header con un `Content-Type` specifico, es: 61 | 62 | ``` 63 | Accept: application/vnd.heroku+json; version=3 64 | ``` 65 | 66 | 67 | #### Supporta ETag per il caching 68 | 69 | Includi un header `ETag` in tutte le risposte, identificando la specifica versione della risorsa restituita. 70 | Questo permetterà gli utenti di aggiungere alla cache le risorse e fare delle richieste con questo valore 71 | aggiungendo un `If-None-Match` header per determinare se la cache debba essere aggiornata o meno. 72 | 73 | 74 | #### Fornisci un parametro Request-Ids per l'analisi 75 | 76 | Includi un parametro `Request-Id` nell'header per ogni risposta della API, popolato con un valore UUID. 77 | Facendo un log di questi valori nel client, server ed altri servizi ausiliari, è possibile ottenere un meccanismo di tracciabilità, diagnosi e debug delle richieste. 78 | 79 | #### Dividi risposte molto lunghe in piu richieste con range 80 | 81 | Risposte molto grandi, dovrebbero essere divise in più richieste usando un header `Range` per specificare quando più dati sono disponibili e come recuperarli. Dai un'occhiata alla documentazione [Heroku Platform API discussion of Ranges](https://devcenter.heroku.com/articles/platform-api-reference#ranges) per i dettagli degli headers delle richieste e delle risposte, codici di stato, limiti, ordinamenti e iterazioni 82 | 83 | ### Richieste 84 | 85 | La sezione delle richieste fornisce una panoramica della struttura per le richieste API. 86 | 87 | #### Accetta JSON serializzato nei corpi delle richieste 88 | 89 | Accetta JSON serializzato nei corpi delle richieste `PUT`/`PATCH`/`POST` oppure in aggiunta ai dati form-encoded. Questo crea simmetria con i il corpo JSON serializzato delle risposte, es: 90 | 91 | ```bash 92 | $ curl -X POST https://service.com/apps \ 93 | -H "Content-Type: application/json" \ 94 | -d '{"name": "demoapp"}' 95 | 96 | { 97 | "id": "01234567-89ab-cdef-0123-456789abcdef", 98 | "name": "demoapp", 99 | "owner": { 100 | "email": "username@example.com", 101 | "id": "01234567-89ab-cdef-0123-456789abcdef" 102 | }, 103 | ... 104 | } 105 | ``` 106 | 107 | ##### Nomi delle risorse 108 | 109 | Usa il nome plurale di un nome di risorsa a meno che la risorsa in questione non sia un nome singolare relativo al sistema stesso (per esempio in alcuni sistemi un determinato utente può avere un solo account). Questo mantiene la consistenza quando ti riferisci alle risorse 110 | 111 | ##### Azioni 112 | 113 | Preferisci dei layout per gli endpoint che non prevedono azioni speciali per una determinata risorsa. 114 | Nel caso in cui sia necessario prevedere la possibilità di azioni speciali, specificale sotto un prefisso standard come `actions`, per definirle in modo chiaro: 115 | 116 | ``` 117 | /resources/:resource/actions/:action 118 | ``` 119 | 120 | es. 121 | 122 | ``` 123 | /runs/{run_id}/actions/stop 124 | ``` 125 | 126 | #### Usa un formato consistente per i percorsi (path) 127 | 128 | #### Caratteri minuscoli per percorsi e attributi 129 | 130 | Usa dei percorsi in minuscolo e separati da trattini, per congruenza con gli hostnames, es: 131 | 132 | ``` 133 | service-api.com/users 134 | service-api.com/app-setups 135 | ``` 136 | 137 | Anche per gli attributi utilizza il minuscolo, ma separando le parole con un underscore, in modo che possano essere scritti 138 | senza l'utilizzo delle virgolette in JavaScript, es: 139 | 140 | ``` 141 | service_class: "first" 142 | ``` 143 | 144 | #### Supporta anche riferimenti non-id per comodita 145 | 146 | In alcuni casi potrebbe essere scomodo per gli utenti finali, fornire ID per 147 | identificare una risorsa. Per esempio, un utente può pensare in termini del nome di una app, ma questa app può essere identificata tramite un UUID. In questi casi, potresti prevedere di accettare entrambi: ID e nome, es: 148 | 149 | ```bash 150 | $ curl https://service.com/apps/{app_id_or_name} 151 | $ curl https://service.com/apps/97addcf0-c182 152 | $ curl https://service.com/apps/www-prod 153 | ``` 154 | Non accettare comunque soltanto un nome, senza la possibilità di specificare un ID 155 | 156 | #### Minimizza annidamento dei percorsi 157 | 158 | Nei model che rappresentano i nostri dati con le relazioni padre/figlio annidate, i percorsi possono diventare 159 | veramente molto lunghi, es: 160 | 161 | ``` 162 | /orgs/{org_id}/apps/{app_id}/dynos/{dyno_id} 163 | ``` 164 | 165 | Limita l'annidamento, preferendo la localizzazione delle risorse nella radice del persorso. 166 | Usa l'annidamento per indicare una raccolta di elementi. Per esempio, 167 | per il caso sopra, dove dyno dipende da app che dipende da org: 168 | 169 | ``` 170 | /orgs/{org_id} 171 | /orgs/{org_id}/apps 172 | /apps/{app_id} 173 | /apps/{app_id}/dynos 174 | /dynos/{dyno_id} 175 | ``` 176 | 177 | ### Risposte 178 | 179 | La sezione delle risposte fornisce una panoramica sui pattern da utilizzare per le risposte della API 180 | 181 | #### Ritorna sempre un codice di stato appropriato 182 | 183 | Ritorna un codice di stato HTTP appropriato per ogni risposta. 184 | Le risposte con esito positivo, dovrebbero essere accompagnate da codici di stato come di seguito: 185 | 186 | * `200`: Richiesta completata con successo per una chiamata (sincrona) `GET`, `DELETE` o 187 | `PATCH`, oppure per una chiamata `PUT` (sincrona) che ha completato l'update di una risorsa 188 | * `201`: Richiesta completata con successo per una chiamata (sincrona) `POST`, o `PUT` che ha creato una nuova risorsa 189 | * `202`: Richiesta completata con successo per una chiamata `POST`, `PUT`, `DELETE`, o `PATCH` che viene processata in modo asincrono 190 | * `206`: Richiesta completata con successo per una chiamata `GET`, dove pero viene restituita una risposta parziale: vedi [Dividi risposte molto lunghe in piu richieste con range](SUMMARY.md#dividi-risposte-molto-lunghe-in-piu-richieste-con-range) 191 | 192 | Fai molta attenzione all'utilizzo dei codici di errore per l'autenticazione e l'autorizzazione: 193 | 194 | * `401 Unauthorized`: Richiesta fallita per utente non autenticato 195 | * `403 Forbidden`: Richiesta fallita perchè l'utente non è autorizzato ad accedere ad una risorsa 196 | 197 | Ritorna codici di errore adatti fornendo informazioni aggiuntive sul tipo di errore: 198 | 199 | * `422 Unprocessable Entity`: La tua richiesta è stata compresa, ma contiene dei parametri non validi. 200 | * `429 Too Many Requests`: Hai superato il limite di richieste, riprova più tardi 201 | * `500 Internal Server Error`: Qualcosa è andato storto, controlla lo stato del sito/servizio ed eventualmente segnala l'errore 202 | 203 | Fai sempre riferimento alle specifiche [HTTP response code spec](https://tools.ietf.org/html/rfc7231#section-6) 204 | per i codici di stato e per gli errori 205 | 206 | #### Fornisci le risorse interamente, quando possibile 207 | 208 | Fornisci la rappresentazione dell'intera risorsa (es. oggetto con tutti gli attributi) 209 | quando possible nella risposta. Fornisci sempre la risorsa completa con un codice 200 o 201, incluse nelle richieste 210 | `PUT`/`PATCH` e `DELETE`, es: 211 | 212 | ```bash 213 | $ curl -X DELETE \ 214 | https://service.com/apps/1f9b/domains/0fd4 215 | 216 | HTTP/1.1 200 OK 217 | Content-Type: application/json;charset=utf-8 218 | ... 219 | { 220 | "created_at": "2012-01-01T12:00:00Z", 221 | "hostname": "subdomain.example.com", 222 | "id": "01234567-89ab-cdef-0123-456789abcdef", 223 | "updated_at": "2012-01-01T12:00:00Z" 224 | } 225 | ``` 226 | 227 | le risposte con codice 202 non includono l'intera rappresentazione della risorsa, 228 | es: 229 | 230 | ```bash 231 | $ curl -X DELETE \ 232 | https://service.com/apps/1f9b/dynos/05bd 233 | 234 | HTTP/1.1 202 Accepted 235 | Content-Type: application/json;charset=utf-8 236 | ... 237 | {} 238 | ``` 239 | 240 | #### Fornisci gli (UU)IDs delle risorse 241 | 242 | Assegna ad ogni risorssa un attributo `id` di default. Usa gli UUIDs a meno che tu 243 | non abbia una buona ragione per non farlo. Non usare gli IDs perchè non sono globalmente 244 | unici, specialmente quando si hanno più instanze del servizio o delle risorse nel servizio, specialmente 245 | gli IDs auto-incrementali. 246 | 247 | Visualizza gli UUIDs in formato `8-4-4-4-12` minuscolo, es: 248 | 249 | ``` 250 | "id": "01234567-89ab-cdef-0123-456789abcdef" 251 | ``` 252 | 253 | #### Fornisci dei timestamps standard 254 | 255 | Fornisci di default i timestamp `created_at` e `updated_at` per le risorse, es: 256 | 257 | ```javascript 258 | { 259 | // ... 260 | "created_at": "2012-01-01T12:00:00Z", 261 | "updated_at": "2012-01-01T13:00:00Z", 262 | // ... 263 | } 264 | ``` 265 | 266 | Questi timestamp possono non avere senso per alcune risorse, in questo caso possono 267 | essere omessi. 268 | 269 | #### Usa date in formato UTC formattate in ISO8601 270 | 271 | Accetta e ritorna le date solo in formato UTC. Visualizza le date nel formato 272 | ISO8601, es: 273 | 274 | ``` 275 | "finished_at": "2012-01-01T12:00:00Z" 276 | ``` 277 | 278 | #### Annida relazioni tramite le chiavi esterne (foreign-key) 279 | 280 | Serializza i riferimenti delle chiavi esterne con un oggetto annidato, es: 281 | 282 | ```javascript 283 | { 284 | "name": "service-production", 285 | "owner": { 286 | "id": "5d8201b0..." 287 | }, 288 | // ... 289 | } 290 | ``` 291 | 292 | Invece di, es: 293 | 294 | ```javascript 295 | { 296 | "name": "service-production", 297 | "owner_id": "5d8201b0...", 298 | // ... 299 | } 300 | ``` 301 | 302 | Questo approccio rende possibile la visualizzazione di più informazioni sulla risorsa 303 | in questione senza dover cambiare la struttura della risposta o introdurre altri campi nella risposta stessa, es: 304 | 305 | ```javascript 306 | { 307 | "name": "service-production", 308 | "owner": { 309 | "id": "5d8201b0...", 310 | "name": "Alice", 311 | "email": "alice@heroku.com" 312 | }, 313 | // ... 314 | } 315 | ``` 316 | 317 | #### Genera errori strutturati 318 | 319 | Genera i corpi di risposta degli errori in modo consistente e strutturato. 320 | Includi un riferimento `id` all'errore in modo che sia leggibile da una macchina, e un 321 | campo `message` che sia comprensible all'utente e, opzionalmente un campo `url` che porta 322 | l'utente ad una descrizione più dettagliata dell'errore in questione e come risolverlo, es: 323 | 324 | ``` 325 | HTTP/1.1 429 Too Many Requests 326 | ``` 327 | 328 | ```json 329 | { 330 | "id": "rate_limit", 331 | "message": "Account reached its API rate limit.", 332 | "url": "https://docs.service.com/rate-limits" 333 | } 334 | ``` 335 | 336 | Documenta il formato dell'errore e il possibile error `id` che l'utente può incontrare. 337 | 338 | #### Visualizza lo stato del limite delle richieste 339 | 340 | Misura i limiti di richieste dai client per proteggere la stabilità del servizio e mantenere una 341 | qualita altà per gli altri clients. Puoi usare un 342 | [token bucket algorithm](http://en.wikipedia.org/wiki/Token_bucket) per misurare e monitorare il 343 | limite delle richieste 344 | 345 | In questo caso, ritorna il numero di richieste rimanenti in ogni richiesta nell'header 346 | `RateLimit-Remaining`. 347 | 348 | #### Mantieni il JSON minimizzato in tutte le risposte 349 | 350 | Gli spazi bianchi extra aumentano inutilmente la dimensione delle richieste/risposte, 351 | inoltre molti clients adottano automaticamente processi di "prettify" sulle risposte JSON. Rimane una scelta 352 | migliore mantenere le risposte JSON minimizzate, es: 353 | 354 | ```json 355 | {"beta":false,"email":"alice@heroku.com","id":"01234567-89ab-cdef-0123-456789abcdef","last_login":"2012-01-01T12:00:00Z","created_at":"2012-01-01T12:00:00Z","updated_at":"2012-01-01T12:00:00Z"} 356 | ``` 357 | 358 | Invece di, es: 359 | 360 | ```json 361 | { 362 | "beta": false, 363 | "email": "alice@heroku.com", 364 | "id": "01234567-89ab-cdef-0123-456789abcdef", 365 | "last_login": "2012-01-01T12:00:00Z", 366 | "created_at": "2012-01-01T12:00:00Z", 367 | "updated_at": "2012-01-01T12:00:00Z" 368 | } 369 | ``` 370 | 371 | Puoi considerare di fornire opzionalmente ai clients l'opportunità di recuperare delle risposte 372 | più verbose (es. `?pretty=true`) o utilizzando un header `Accept` (es. `Accept: application/vnd.heroku+json; version=3; indent=4;`). 373 | 374 | ### Artefatti 375 | 376 | La sezione artefatti descrive gli oggetti che vengono utilizzati per gestire la progettazione delle API 377 | 378 | #### Fornisci uno schema JSON interpretabile 379 | 380 | Fornisci uno schema JSON interpretabile per descrivere in maniera formale e precisa la tua API. 381 | Puoi usare [prmd](https://github.com/interagent/prmd) per gestire lo schema e assicurarti della sua 382 | validità usando il comando `prmd verify`. 383 | 384 | #### Fornisci una documentazione comprensibile allo sviluppatore 385 | 386 | Fornisci una documentazione comprensibile che lo sviluppatore e i clients possono consultare per 387 | usare la tua API. 388 | 389 | Se crei uno schema utilizzando prmd come descritto sopra, potrai facilmente generare un documento in formato 390 | Markdown per tutti gli endpoints usando il comando `prmd doc`. 391 | 392 | Oltre alle specifiche degli endpoints, fornisci una panoramica della API con le seguenti 393 | informazioni: 394 | 395 | * Autenticazione, specificando come ottenere ed usare un access token 396 | * Stabilità della API e versionamento, specificando come scegliere la versione della API 397 | * I comuni headeer delle richieste e delle risposte 398 | * Errori in formato serializzato 399 | * Esempi di utilizzo della tua API in diversi linguaggi 400 | 401 | #### Fornisci degli esempi 402 | 403 | Fornisci dei semplici esempi eseguibili che gli utenti possano provare 404 | velocemente tramite i loro terminali, per vedere il funzionamento delle chiamate alle API. 405 | Per essere più chiaro possibile, descrivi gli esempi in modo molto dettagliato, per diminuire 406 | in maniera considerevole il lavoro dell'utente che dovrà provare ed usare l'API, es: 407 | 408 | ```bash 409 | $ export TOKEN=... # acquire from dashboard 410 | $ curl -is https://$TOKEN@service.com/users 411 | ``` 412 | 413 | Se usi [prmd](https://github.com/interagent/prmd) per generare la documentazione in formato Markdown, 414 | otterrai automaticamente degli esempi per ogni endpoint. 415 | 416 | #### Specifica la stabilità della tua API 417 | 418 | Specifica la stabilità della tua API oppure dei vari endpoints per quanto riguarda la maturità e la stabilità 419 | della stessa, es. tramite dei flag prototype/development/production. 420 | 421 | Dai un'occhiata a [Heroku API compatibility policy](https://devcenter.heroku.com/articles/api-compatibility-policy) 422 | per possibili cambiamenti nella stabilità o nella gestione delle policy. 423 | 424 | Una volta che la tua API è pronta per andare in produzione ed è stabile, non fare cambiamenti non retrocompatibili. 425 | Se hai bisogno di fare dei cambiamenti non retrocompatibili, crea una nuova API con un nuovo numero di versione. 426 | 427 | 428 | 429 | --------------------------------------------------------------------------------