Repository: interagent/http-api-design Branch: master Commit: 5fd8c92fb18c Files: 40 Total size: 44.8 KB Directory structure: gitextract_2u_v2rie/ ├── 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 ================================================ FILE CONTENTS ================================================ ================================================ FILE: CONTRIBUTING.md ================================================ ## Contributing We welcome contributions to this guide and discussion about its contents. Please open an issue or pull request on this repository to propose a change. ================================================ FILE: CONTRIBUTORS.md ================================================ * Andrew Couch * Ben Hockey * Brandur * Brandur * C. T. Lin * David Paschich * Dyego Costa * Gordon Yeu * James Manning * Jonathan Hanson * Jonathan Roes * Karl Coelho * Keith Cirkel * Mario Vejlupek * Mark McGranaghan * Matt Haggard * Richard Hoberman * Stefano Uliari * Steve * Steven Beeckman * Thomas Orozco * Tom Christie * Travis Paul * Wesley Beary * Wesley Beary * e3 * geemus ================================================ FILE: LANGS.md ================================================ * [English](en) * [Italian](it) ================================================ FILE: LICENSE.md ================================================ ## License Copyright the [project contributors](CONTRIBUTORS.md). Released under a [Creative Commons Attribution 3.0 Unported License](http://creativecommons.org/licenses/by/3.0/). ================================================ FILE: README.md ================================================ # HTTP API Design Guide This guide describes a set of HTTP+JSON API design practices, originally extracted from work on the [Heroku Platform API](https://devcenter.heroku.com/articles/platform-api-reference). This guide informs additions to that API and also guides new internal APIs at Heroku. We hope it’s also of interest to API designers outside of Heroku. Our goals here are consistency and focusing on business logic while avoiding design bikeshedding. We’re looking for _a good, consistent, well-documented way_ to design APIs, not necessarily _the only/ideal way_. We assume you’re familiar with the basics of HTTP+JSON APIs and won’t cover all of the fundamentals of those in this guide. Available for online reading and in multiple formats at [gitbook](https://geemus.gitbooks.io/http-api-design). We welcome [contributions](https://github.com/interagent/http-api-design/blob/master/CONTRIBUTING.md) to this guide. See [Summary](en/SUMMARY.md) for Table of Contents. For the best reading experience, we recommend reading via [GitBook](https://geemus.gitbooks.io/http-api-design). ### Gitbook Translations * [English](https://geemus.gitbooks.io/http-api-design/content/en/index.html) * [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/) * [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/) ### Git Translations * [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/) * [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/) * [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/) * [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/) * [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/) * [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/) ================================================ FILE: en/README.md ================================================ # HTTP API Design Guide This guide describes a set of HTTP+JSON API design practices, originally extracted from work on the [Heroku Platform API](https://devcenter.heroku.com/articles/platform-api-reference). This guide informs additions to that API and also guides new internal APIs at Heroku. We hope it’s also of interest to API designers outside of Heroku. Our goals here are consistency and focusing on business logic while avoiding design bikeshedding. We’re looking for _a good, consistent, well-documented way_ to design APIs, not necessarily _the only/ideal way_. We assume you’re familiar with the basics of HTTP+JSON APIs and won’t cover all of the fundamentals of those in this guide. Available for online reading and in multiple formats at [gitbook](https://geemus.gitbooks.io/http-api-design/). We welcome [contributions](https://github.com/interagent/http-api-design/blob/master/CONTRIBUTING.md) to this guide. See [Summary](https://github.com/interagent/http-api-design/blob/master/en/SUMMARY.md) for Table of Contents. ### Translations * [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/) * [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/) * [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/) * [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/) * [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/) * [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/) ================================================ FILE: en/SUMMARY.md ================================================ # HTTP API Design Guide * [Foundations](foundations/README.md) * [Separate Concerns](foundations/separate-concerns.md) * [Require Secure Connections](foundations/require-secure-connections.md) * [Require Versioning in the Accepts Header](foundations/require-versioning-in-the-accepts-header.md) * [Support ETags for Caching](foundations/support-etags-for-caching.md) * [Provide Request-Ids for Introspection](foundations/provide-request-ids-for-introspection.md) * [Divide Large Responses Across Requests with Ranges](foundations/divide-large-responses-across-requests-with-ranges.md) * [Requests](requests/README.md) * [Accept serialized JSON in request bodies](requests/accept-serialized-json-in-request-bodies.md) * [Resource names](requests/resource-names.md) * [Actions](requests/actions.md) * [Use consistent path formats](requests/use-consistent-path-formats.md) * [Downcase paths and attributes](requests/downcase-paths-and-attributes.md) * [Support non-id dereferencing for convenience](requests/support-non-id-dereferencing-for-convenience.md) * [Minimize path nesting](requests/minimize-path-nesting.md) * [Responses](responses/README.md) * [Return appropriate status codes](responses/return-appropriate-status-codes.md) * [Provide full resources where available](responses/provide-full-resources-where-available.md) * [Provide resource (UU)IDs](responses/provide-resource-uuids.md) * [Provide standard timestamps](responses/provide-standard-timestamps.md) * [Provide standard response types](responses/provide-standard-response-types.md) * [Use UTC times formatted in ISO8601](responses/use-utc-times-formatted-in-iso8601.md) * [Nest foreign key relations](responses/nest-foreign-key-relations.md) * [Generate structured errors](responses/generate-structured-errors.md) * [Show rate limit status](responses/show-rate-limit-status.md) * [Keep JSON minified in all responses](responses/keep-json-minified-in-all-responses.md) * [Artifacts](artifacts/README.md) * [Provide machine-readable JSON schema](artifacts/provide-machine-readable-json-schema.md) * [Provide human-readable docs](artifacts/provide-human-readable-docs.md) * [Provide executable examples](artifacts/provide-executable-examples.md) * [Describe stability](artifacts/describe-stability.md) ================================================ FILE: en/artifacts/README.md ================================================ ### Artifacts The Artifacts section describes the physical objects we use to manage and discuss API designs and patterns. ================================================ FILE: en/artifacts/describe-stability.md ================================================ #### Describe stability Describe the stability of your API or its various endpoints according to its maturity and stability, e.g. with prototype/development/production flags. See the [Heroku API compatibility policy](https://devcenter.heroku.com/articles/api-compatibility-policy) for a possible stability and change management approach. Once your API is declared production-ready and stable, do not make backwards incompatible changes within that API version. If you need to make backwards-incompatible changes, create a new API with an incremented version number. ================================================ FILE: en/artifacts/provide-executable-examples.md ================================================ #### Provide executable examples Provide executable examples that users can type directly into their terminals to see working API calls. To the greatest extent possible, these examples should be usable verbatim, to minimize the amount of work a user needs to do to try the API, e.g.: ```bash $ export TOKEN=... # acquire from dashboard $ curl -is https://$TOKEN@service.com/users ``` If you use [prmd](https://github.com/interagent/prmd) to generate Markdown docs, you will get examples for each endpoint for free. ================================================ FILE: en/artifacts/provide-human-readable-docs.md ================================================ #### Provide human-readable docs Provide human-readable documentation that client developers can use to understand your API. If you create a schema with prmd as described above, you can easily generate Markdown docs for all endpoints with `prmd doc`. In addition to endpoint details, provide an API overview with information about: * Authentication, including acquiring and using authentication tokens. * API stability and versioning, including how to select the desired API version. * Common request and response headers. * Error serialization format. * Examples of using the API with clients in different languages. ================================================ FILE: en/artifacts/provide-machine-readable-json-schema.md ================================================ #### Provide machine-readable JSON schema Provide a machine-readable schema to exactly specify your API. Use [prmd](https://github.com/interagent/prmd) to manage your schema, and ensure it validates with `prmd verify`. ================================================ FILE: en/foundations/README.md ================================================ ### Foundations The Foundations section outlines the design principles upon which the rest of the guide builds. ================================================ FILE: en/foundations/divide-large-responses-across-requests-with-ranges.md ================================================ #### Divide Large Responses Across Requests with Ranges Large responses should be broken across multiple requests using `Range` headers to specify when more data is available and how to retrieve it. See the [Heroku Platform API discussion of Ranges](https://devcenter.heroku.com/articles/platform-api-reference#ranges) for the details of request and response headers, status codes, limits, ordering, and iteration. ================================================ FILE: en/foundations/provide-request-ids-for-introspection.md ================================================ #### Provide Request-Ids for Introspection Include a `Request-Id` header in each API response, populated with a UUID value. By logging these values on the client, server and any backing services, it provides a mechanism to trace, diagnose and debug requests. ================================================ FILE: en/foundations/require-secure-connections.md ================================================ #### Require Secure Connections Require secure connections with TLS to access the API, without exception. It’s not worth trying to figure out or explain when it is OK to use TLS and when it’s not. Just require TLS for everything. Ideally, simply reject any non-TLS requests by not responding to requests for http or port 80 to avoid any insecure data exchange. In environments where this is not possible, respond with `403 Forbidden`. Redirects are discouraged since they allow sloppy/bad client behaviour without providing any clear gain. Clients that rely on redirects double up on server traffic and render TLS useless since sensitive data will already have been exposed during the first call. ================================================ FILE: en/foundations/require-versioning-in-the-accepts-header.md ================================================ #### Require Versioning in the Accepts Header Versioning and the transition between versions can be one of the more challenging aspects of designing and operating an API. As such, it is best to start with some mechanisms in place to mitigate this from the start. To prevent surprise, breaking changes to users, it is best to require a version be specified with all requests. Default versions should be avoided as they are very difficult, at best, to change in the future. It is best to provide version specification in the headers, with other metadata, using the `Accept` header with a custom content type, e.g.: ``` Accept: application/vnd.heroku+json; version=3 ``` ================================================ FILE: en/foundations/separate-concerns.md ================================================ #### Separate Concerns Keep things simple while designing by separating the concerns between the different parts of the request and response cycle. Keeping simple rules here allows for greater focus on larger and harder problems. Requests and responses will be made to address a particular resource or collection. Use the path to indicate identity, the body to transfer the contents and headers to communicate metadata. Query params may be used as a means to pass header information also in edge cases, but headers are preferred as they are more flexible and can convey more diverse information. ================================================ FILE: en/foundations/support-etags-for-caching.md ================================================ #### Support ETags for Caching Include an `ETag` header in all responses, identifying the specific version of the returned resource. This allows users to cache resources and use requests with this value in the `If-None-Match` header to determine if the cache should be updated. ================================================ FILE: en/requests/README.md ================================================ ### Requests The Requests section provides an overview of patterns for API requests. ================================================ FILE: en/requests/accept-serialized-json-in-request-bodies.md ================================================ #### Accept serialized JSON in request bodies Accept serialized JSON on `PUT`/`PATCH`/`POST` request bodies, either instead of or in addition to form-encoded data. This creates symmetry with JSON-serialized response bodies, e.g.: ```bash $ curl -X POST https://service.com/apps \ -H "Content-Type: application/json" \ -d '{"name": "demoapp"}' { "id": "01234567-89ab-cdef-0123-456789abcdef", "name": "demoapp", "owner": { "email": "username@example.com", "id": "01234567-89ab-cdef-0123-456789abcdef" }, ... } ``` ================================================ FILE: en/requests/actions.md ================================================ ##### Actions Prefer endpoint configurations that don’t require special actions. In cases where actions are needed, clearly delineate them with the `actions` prefix: ``` /resources/:resource/actions/:action ``` e.g. to stop a particular run: ``` /runs/{run_id}/actions/stop ``` Actions on collections should also be minimized. Where needed, they should use a top-level actions delineation to avoid namespace conflicts and clearly show the scope of action: ``` /actions/:action/resources ``` e.g. to restart all servers: ``` /actions/restart/servers ``` ================================================ FILE: en/requests/downcase-paths-and-attributes.md ================================================ #### Downcase paths and attributes Use downcased and dash-separated path names, for alignment with hostnames, e.g: ``` service-api.com/users service-api.com/app-setups ``` Downcase attributes as well, but use underscore separators so that attribute names can be typed without quotes in JavaScript, e.g.: ``` service_class: "first" ``` ================================================ FILE: en/requests/minimize-path-nesting.md ================================================ #### Minimize path nesting In data models with nested parent/child resource relationships, paths may become deeply nested, e.g.: ``` /orgs/{org_id}/apps/{app_id}/dynos/{dyno_id} ``` Limit nesting depth by preferring to locate resources at the root path. Use nesting to indicate scoped collections. For example, for the case above where a dyno belongs to an app belongs to an org: ``` /orgs/{org_id} /orgs/{org_id}/apps /apps/{app_id} /apps/{app_id}/dynos /dynos/{dyno_id} ``` ================================================ FILE: en/requests/resource-names.md ================================================ ##### Resource names 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. ================================================ FILE: en/requests/support-non-id-dereferencing-for-convenience.md ================================================ #### Support non-id dereferencing for convenience In some cases it may be inconvenient for end-users to provide IDs to identify a resource. For example, a user may think in terms of a Heroku app name, but that app may be identified by a UUID. In these cases you may want to accept both an id or name, e.g.: ```bash $ curl https://service.com/apps/{app_id_or_name} $ curl https://service.com/apps/97addcf0-c182 $ curl https://service.com/apps/www-prod ``` Do not accept only names to the exclusion of IDs. ================================================ FILE: en/requests/use-consistent-path-formats.md ================================================ #### Use consistent path formats ================================================ FILE: en/responses/README.md ================================================ ### Responses The Responses section provides an overview of patterns for API responses. ================================================ FILE: en/responses/generate-structured-errors.md ================================================ #### Generate structured errors Generate consistent, structured response bodies on errors. Include a machine-readable error `id`, a human-readable error `message`, and optionally a `url` pointing the client to further information about the error and how to resolve it, e.g.: ``` HTTP/1.1 429 Too Many Requests ``` ```json { "id": "rate_limit", "message": "Account reached its API rate limit.", "url": "https://docs.service.com/rate-limits" } ``` Document your error format and the possible error `id`s that clients may encounter. ================================================ FILE: en/responses/keep-json-minified-in-all-responses.md ================================================ #### Keep JSON minified in all responses Extra whitespace adds needless response size to requests, and many clients for human consumption will automatically "prettify" JSON output. It is best to keep JSON responses minified e.g.: ```json {"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"} ``` Instead of e.g.: ```json { "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" } ``` You may consider optionally providing a way for clients to retrieve more verbose response, either via a query parameter (e.g. `?pretty=true`) or via an `Accept` header param (e.g. `Accept: application/vnd.heroku+json; version=3; indent=4;`). ================================================ FILE: en/responses/nest-foreign-key-relations.md ================================================ #### Nest foreign key relations Serialize foreign key references with a nested object, e.g.: ```javascript { "name": "service-production", "owner": { "id": "5d8201b0..." }, // ... } ``` Instead of e.g.: ```javascript { "name": "service-production", "owner_id": "5d8201b0...", // ... } ``` This approach makes it possible to inline more information about the related resource without having to change the structure of the response or introduce more top-level response fields, e.g.: ```javascript { "name": "service-production", "owner": { "id": "5d8201b0...", "email": "alice@heroku.com" }, // ... } ``` 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. To avoid inconsistency and confusion, serialize either: - **foreign keys** only - values the full record can be looked up with, like `id`, `slug`, `email`. - **full record**, all fields (this would be an "embedded record") ================================================ FILE: en/responses/provide-full-resources-where-available.md ================================================ #### Provide full resources where available Provide the full resource representation (i.e. the object with all attributes) whenever possible in the response. Always provide the full resource on 200 and 201 responses, including `PUT`/`PATCH` and `DELETE` requests, e.g.: ```bash $ curl -X DELETE \ https://service.com/apps/1f9b/domains/0fd4 HTTP/1.1 200 OK Content-Type: application/json;charset=utf-8 ... { "created_at": "2012-01-01T12:00:00Z", "hostname": "subdomain.example.com", "id": "01234567-89ab-cdef-0123-456789abcdef", "updated_at": "2012-01-01T12:00:00Z" } ``` 202 responses will not include the full resource representation, e.g.: ```bash $ curl -X DELETE \ https://service.com/apps/1f9b/dynos/05bd HTTP/1.1 202 Accepted Content-Type: application/json;charset=utf-8 ... {} ``` ================================================ FILE: en/responses/provide-resource-uuids.md ================================================ #### Provide resource (UU)IDs Give each resource an `id` attribute by default. Use UUIDs unless you have a very good reason not to. Don’t use IDs that won’t be globally unique across instances of the service or other resources in the service, especially auto-incrementing IDs. Render UUIDs in downcased `8-4-4-4-12` format, e.g.: ``` "id": "01234567-89ab-cdef-0123-456789abcdef" ``` ================================================ FILE: en/responses/provide-standard-response-types.md ================================================ #### Provide standard response types This document describes the acceptable values for each of JSON's basic data types. ### String * Acceptable values: * string * `null` e.g: ```javascript [ { "description": "very descriptive description." }, { "description": null }, ] ``` ### Boolean * Acceptable values: * true * false e.g: ```javascript [ { "provisioned_licenses": true }, { "provisioned_licenses": false }, ] ``` ### Number * Acceptable values: * number * `null` Note: some JSON parsers will return numbers with a precision of over 15 decimal places as strings. If you need precision greater than 15 decimals, always return a string for that value. If not, convert those strings to numbers so that consumers of the API always know what value type to expect. e.g: ```javascript [ { "average": 27.123 }, { "average": 12.123456789012 }, ] ``` ### Array * Acceptable values: * array Note: Return an empty array rather than `NULL` when there are no values in the array. e.g: ```javascript [ { "child_ids": [1, 2, 3, 4], }, { "child_ids": [], } ] ``` ### Object * Acceptable values: * object * null e.g: ```javascript [ { "name": "service-production", "owner": { "id": "5d8201b0..." } }, { "name": "service-staging", "owner": null } ] ``` ================================================ FILE: en/responses/provide-standard-timestamps.md ================================================ #### Provide standard timestamps Provide `created_at` and `updated_at` timestamps for resources by default, e.g: ```javascript { // ... "created_at": "2012-01-01T12:00:00Z", "updated_at": "2012-01-01T13:00:00Z", // ... } ``` These timestamps may not make sense for some resources, in which case they can be omitted. ================================================ FILE: en/responses/return-appropriate-status-codes.md ================================================ #### Return appropriate status codes Return appropriate HTTP status codes with each response. Successful responses should be coded according to this guide: * `200`: Request succeeded for a `GET`, `POST`, `DELETE`, or `PATCH` call that completed synchronously, or a `PUT` call that synchronously updated an existing resource * `201`: Request succeeded for a `POST`, or `PUT` call that synchronously created a new resource. It is also best practice to provide a 'Location' header pointing to the newly created resource. This is particularly useful in the `POST` context as the new resource will have a different URL than the original request. * `202`: Request accepted for a `POST`, `PUT`, `DELETE`, or `PATCH` call that will be processed asynchronously * `206`: Request succeeded on `GET`, but only a partial response returned: see [above on ranges](../foundations/divide-large-responses-across-requests-with-ranges.md) Pay attention to the use of authentication and authorization error codes: * `401 Unauthorized`: Request failed because user is not authenticated * `403 Forbidden`: Request failed because user does not have authorization to access a specific resource Return suitable codes to provide additional information when there are errors: * `422 Unprocessable Entity`: Your request was understood, but contained invalid parameters * `429 Too Many Requests`: You have been rate-limited, retry later * `500 Internal Server Error`: Something went wrong on the server, check status site and/or report the issue Refer to the [HTTP response code spec](https://tools.ietf.org/html/rfc7231#section-6) for guidance on status codes for user error and server error cases. ================================================ FILE: en/responses/show-rate-limit-status.md ================================================ #### Show rate limit status Rate limit requests from clients to protect the health of the service and maintain high service quality for other clients. You can use a [token bucket algorithm](http://en.wikipedia.org/wiki/Token_bucket) to quantify request limits. Return the remaining number of request tokens with each request in the `RateLimit-Remaining` response header. ================================================ FILE: en/responses/use-utc-times-formatted-in-iso8601.md ================================================ #### Use UTC times formatted in ISO8601 Accept and return times in UTC only. Render times in ISO8601 format, e.g.: ``` "finished_at": "2012-01-01T12:00:00Z" ``` ================================================ FILE: it/README.md ================================================ # Guida alla progettazione di API HTTP 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). 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. 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. 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. La guida è disponibile in diversi formati a questo link [gitbook](https://www.gitbook.com/read/book/geemus/http-api-design) Accettiamo volentieri [contributi](../CONTRIBUTING.md) alla guida. Vai al [Sommario](SUMMARY.md) per l'indice dei contenuti. ### Traduzioni * [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/) * [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/) * [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/) * [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/) * [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/) * [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/) ================================================ FILE: it/SUMMARY.md ================================================ # Guida alla progettazione delle API HTTP * [Fondamenti](SUMMARY.md#fondamenti) * [Concetti separati](SUMMARY.md#concetti-separati) * [Utlizza una connessione sicura (TLS)](SUMMARY.md#utlizza-una-connessione-sicura-(tls)) * [Richiedi il versioning negli Accept Headers](SUMMARY.md#richiedi-il-versioning-negli-accept-headers) * [Supporta ETag per il caching](SUMMARY.md#supporta-etag-per-il-caching) * [Fornisci un parametro Request-Ids per l'analisi](SUMMARY.md#fornisci-un-parametro-request-ids-per-lanalisi) * [Dividi risposte molto lunghe in piu richieste con range](SUMMARY.md#dividi-risposte-molto-lunghe-in-piu-richieste-con-range) * [Richieste](SUMMARY.md#richieste) * [Accetta JSON serializzato nei corpi delle richieste](SUMMARY.md#accetta-json-serializzato-nei-corpi-delle-richieste) * [Nomi delle risorse](SUMMARY.md#nomi-delle-risorse) * [Azioni](SUMMARY.md#azioni) * [Usa un formato consistente per i percorsi (path)](SUMMARY.md#usa-un-formato-consistente-per-i-percorsi-path) * [Caratteri minuscoli per percorsi e attributi](SUMMARY.md#caratteri-minuscoli-per-percorsi-e-attributi) * [Supporta anche riferimenti non-id per comodita](SUMMARY.md#supporta-anche-riferimenti-non-id-per-comodita) * [Minimizza annidamento dei percorsi](SUMMARY.md#minimizza-annidamento-dei-percorsi) * [Risposte](SUMMARY.md#risposte) * [Ritorna sempre un codice di stato appropriato](SUMMARY.md#ritorna-sempre-un-codice-di-stato-appropriato) * [Fornisci le risorse interamente, quando possibile](SUMMARY.md#fornisci-le-risorse-interamente-quando-possibile) * [Fornisci gli (UU)IDs delle risorse](SUMMARY.md#fornisci-gli-uuids-delle-risorse) * [Fornisci dei timestamps standard](SUMMARY.md#fornisci-dei-timestamps-standard) * [Usa date in formato UTC formattate in ISO8601](SUMMARY.md#usa-date-in-formato-utc-formattate-in-iso8601) * [Annida relazioni tramite le chiavi esterne (foreign-key)](SUMMARY.md#annida-relazioni-tramite-le-chiavi-esterne-foreign-key) * [Genera errori strutturati](SUMMARY.md#genera-errori-strutturati) * [Visualizza lo stato del limite delle richieste](SUMMARY.md#visualizza-lo-stato-del-limite-delle-richieste) * [Mantieni il JSON minimizzato in tutte le risposte](SUMMARY.md#mantieni-il-json-minimizzato-in-tutte-le-risposte) * [Artefatti](SUMMARY.md#artefatti) * [Fornisci uno schema JSON interpretabile](SUMMARY.md#fornisci-uno-schema-json-interpretabile) * [Fornisci una documentazione comprensibile allo sviluppatore](SUMMARY.md#fornisci-una-documentazione-comprensibile-allo-sviluppatore) * [Fornisci degli esempi](SUMMARY.md#fornisci-degli-esempi) * [Specifica la stabilità della tua API](SUMMARY.md#specifica-la-stabilita-della-tua-api) ### Fondamenti Questa sezione illustra i principi di progettazione, sui quali si basa questa guida #### Concetti separati 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. 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. #### Utlizza una connessione sicura (TLS) Richiedi una connessione sicura con protocollo TLS per accedere alle APIs, senza eccezioni. Non importa cercare di capire quando è opportuno usare TLS oppure quando non lo è. Semplicemente richiedila sempre. 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`. 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 #### Richiedi il versioning negli Accept Headers 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. 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. 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: ``` Accept: application/vnd.heroku+json; version=3 ``` #### Supporta ETag per il caching Includi un header `ETag` in tutte le risposte, identificando la specifica versione della risorsa restituita. Questo permetterà gli utenti di aggiungere alla cache le risorse e fare delle richieste con questo valore aggiungendo un `If-None-Match` header per determinare se la cache debba essere aggiornata o meno. #### Fornisci un parametro Request-Ids per l'analisi Includi un parametro `Request-Id` nell'header per ogni risposta della API, popolato con un valore UUID. Facendo un log di questi valori nel client, server ed altri servizi ausiliari, è possibile ottenere un meccanismo di tracciabilità, diagnosi e debug delle richieste. #### Dividi risposte molto lunghe in piu richieste con range 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 ### Richieste La sezione delle richieste fornisce una panoramica della struttura per le richieste API. #### Accetta JSON serializzato nei corpi delle richieste 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: ```bash $ curl -X POST https://service.com/apps \ -H "Content-Type: application/json" \ -d '{"name": "demoapp"}' { "id": "01234567-89ab-cdef-0123-456789abcdef", "name": "demoapp", "owner": { "email": "username@example.com", "id": "01234567-89ab-cdef-0123-456789abcdef" }, ... } ``` ##### Nomi delle risorse 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 ##### Azioni Preferisci dei layout per gli endpoint che non prevedono azioni speciali per una determinata risorsa. Nel caso in cui sia necessario prevedere la possibilità di azioni speciali, specificale sotto un prefisso standard come `actions`, per definirle in modo chiaro: ``` /resources/:resource/actions/:action ``` es. ``` /runs/{run_id}/actions/stop ``` #### Usa un formato consistente per i percorsi (path) #### Caratteri minuscoli per percorsi e attributi Usa dei percorsi in minuscolo e separati da trattini, per congruenza con gli hostnames, es: ``` service-api.com/users service-api.com/app-setups ``` Anche per gli attributi utilizza il minuscolo, ma separando le parole con un underscore, in modo che possano essere scritti senza l'utilizzo delle virgolette in JavaScript, es: ``` service_class: "first" ``` #### Supporta anche riferimenti non-id per comodita In alcuni casi potrebbe essere scomodo per gli utenti finali, fornire ID per 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: ```bash $ curl https://service.com/apps/{app_id_or_name} $ curl https://service.com/apps/97addcf0-c182 $ curl https://service.com/apps/www-prod ``` Non accettare comunque soltanto un nome, senza la possibilità di specificare un ID #### Minimizza annidamento dei percorsi Nei model che rappresentano i nostri dati con le relazioni padre/figlio annidate, i percorsi possono diventare veramente molto lunghi, es: ``` /orgs/{org_id}/apps/{app_id}/dynos/{dyno_id} ``` Limita l'annidamento, preferendo la localizzazione delle risorse nella radice del persorso. Usa l'annidamento per indicare una raccolta di elementi. Per esempio, per il caso sopra, dove dyno dipende da app che dipende da org: ``` /orgs/{org_id} /orgs/{org_id}/apps /apps/{app_id} /apps/{app_id}/dynos /dynos/{dyno_id} ``` ### Risposte La sezione delle risposte fornisce una panoramica sui pattern da utilizzare per le risposte della API #### Ritorna sempre un codice di stato appropriato Ritorna un codice di stato HTTP appropriato per ogni risposta. Le risposte con esito positivo, dovrebbero essere accompagnate da codici di stato come di seguito: * `200`: Richiesta completata con successo per una chiamata (sincrona) `GET`, `DELETE` o `PATCH`, oppure per una chiamata `PUT` (sincrona) che ha completato l'update di una risorsa * `201`: Richiesta completata con successo per una chiamata (sincrona) `POST`, o `PUT` che ha creato una nuova risorsa * `202`: Richiesta completata con successo per una chiamata `POST`, `PUT`, `DELETE`, o `PATCH` che viene processata in modo asincrono * `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) Fai molta attenzione all'utilizzo dei codici di errore per l'autenticazione e l'autorizzazione: * `401 Unauthorized`: Richiesta fallita per utente non autenticato * `403 Forbidden`: Richiesta fallita perchè l'utente non è autorizzato ad accedere ad una risorsa Ritorna codici di errore adatti fornendo informazioni aggiuntive sul tipo di errore: * `422 Unprocessable Entity`: La tua richiesta è stata compresa, ma contiene dei parametri non validi. * `429 Too Many Requests`: Hai superato il limite di richieste, riprova più tardi * `500 Internal Server Error`: Qualcosa è andato storto, controlla lo stato del sito/servizio ed eventualmente segnala l'errore Fai sempre riferimento alle specifiche [HTTP response code spec](https://tools.ietf.org/html/rfc7231#section-6) per i codici di stato e per gli errori #### Fornisci le risorse interamente, quando possibile Fornisci la rappresentazione dell'intera risorsa (es. oggetto con tutti gli attributi) quando possible nella risposta. Fornisci sempre la risorsa completa con un codice 200 o 201, incluse nelle richieste `PUT`/`PATCH` e `DELETE`, es: ```bash $ curl -X DELETE \ https://service.com/apps/1f9b/domains/0fd4 HTTP/1.1 200 OK Content-Type: application/json;charset=utf-8 ... { "created_at": "2012-01-01T12:00:00Z", "hostname": "subdomain.example.com", "id": "01234567-89ab-cdef-0123-456789abcdef", "updated_at": "2012-01-01T12:00:00Z" } ``` le risposte con codice 202 non includono l'intera rappresentazione della risorsa, es: ```bash $ curl -X DELETE \ https://service.com/apps/1f9b/dynos/05bd HTTP/1.1 202 Accepted Content-Type: application/json;charset=utf-8 ... {} ``` #### Fornisci gli (UU)IDs delle risorse Assegna ad ogni risorssa un attributo `id` di default. Usa gli UUIDs a meno che tu non abbia una buona ragione per non farlo. Non usare gli IDs perchè non sono globalmente unici, specialmente quando si hanno più instanze del servizio o delle risorse nel servizio, specialmente gli IDs auto-incrementali. Visualizza gli UUIDs in formato `8-4-4-4-12` minuscolo, es: ``` "id": "01234567-89ab-cdef-0123-456789abcdef" ``` #### Fornisci dei timestamps standard Fornisci di default i timestamp `created_at` e `updated_at` per le risorse, es: ```javascript { // ... "created_at": "2012-01-01T12:00:00Z", "updated_at": "2012-01-01T13:00:00Z", // ... } ``` Questi timestamp possono non avere senso per alcune risorse, in questo caso possono essere omessi. #### Usa date in formato UTC formattate in ISO8601 Accetta e ritorna le date solo in formato UTC. Visualizza le date nel formato ISO8601, es: ``` "finished_at": "2012-01-01T12:00:00Z" ``` #### Annida relazioni tramite le chiavi esterne (foreign-key) Serializza i riferimenti delle chiavi esterne con un oggetto annidato, es: ```javascript { "name": "service-production", "owner": { "id": "5d8201b0..." }, // ... } ``` Invece di, es: ```javascript { "name": "service-production", "owner_id": "5d8201b0...", // ... } ``` Questo approccio rende possibile la visualizzazione di più informazioni sulla risorsa in questione senza dover cambiare la struttura della risposta o introdurre altri campi nella risposta stessa, es: ```javascript { "name": "service-production", "owner": { "id": "5d8201b0...", "name": "Alice", "email": "alice@heroku.com" }, // ... } ``` #### Genera errori strutturati Genera i corpi di risposta degli errori in modo consistente e strutturato. Includi un riferimento `id` all'errore in modo che sia leggibile da una macchina, e un campo `message` che sia comprensible all'utente e, opzionalmente un campo `url` che porta l'utente ad una descrizione più dettagliata dell'errore in questione e come risolverlo, es: ``` HTTP/1.1 429 Too Many Requests ``` ```json { "id": "rate_limit", "message": "Account reached its API rate limit.", "url": "https://docs.service.com/rate-limits" } ``` Documenta il formato dell'errore e il possibile error `id` che l'utente può incontrare. #### Visualizza lo stato del limite delle richieste Misura i limiti di richieste dai client per proteggere la stabilità del servizio e mantenere una qualita altà per gli altri clients. Puoi usare un [token bucket algorithm](http://en.wikipedia.org/wiki/Token_bucket) per misurare e monitorare il limite delle richieste In questo caso, ritorna il numero di richieste rimanenti in ogni richiesta nell'header `RateLimit-Remaining`. #### Mantieni il JSON minimizzato in tutte le risposte Gli spazi bianchi extra aumentano inutilmente la dimensione delle richieste/risposte, inoltre molti clients adottano automaticamente processi di "prettify" sulle risposte JSON. Rimane una scelta migliore mantenere le risposte JSON minimizzate, es: ```json {"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"} ``` Invece di, es: ```json { "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" } ``` Puoi considerare di fornire opzionalmente ai clients l'opportunità di recuperare delle risposte più verbose (es. `?pretty=true`) o utilizzando un header `Accept` (es. `Accept: application/vnd.heroku+json; version=3; indent=4;`). ### Artefatti La sezione artefatti descrive gli oggetti che vengono utilizzati per gestire la progettazione delle API #### Fornisci uno schema JSON interpretabile Fornisci uno schema JSON interpretabile per descrivere in maniera formale e precisa la tua API. Puoi usare [prmd](https://github.com/interagent/prmd) per gestire lo schema e assicurarti della sua validità usando il comando `prmd verify`. #### Fornisci una documentazione comprensibile allo sviluppatore Fornisci una documentazione comprensibile che lo sviluppatore e i clients possono consultare per usare la tua API. Se crei uno schema utilizzando prmd come descritto sopra, potrai facilmente generare un documento in formato Markdown per tutti gli endpoints usando il comando `prmd doc`. Oltre alle specifiche degli endpoints, fornisci una panoramica della API con le seguenti informazioni: * Autenticazione, specificando come ottenere ed usare un access token * Stabilità della API e versionamento, specificando come scegliere la versione della API * I comuni headeer delle richieste e delle risposte * Errori in formato serializzato * Esempi di utilizzo della tua API in diversi linguaggi #### Fornisci degli esempi Fornisci dei semplici esempi eseguibili che gli utenti possano provare velocemente tramite i loro terminali, per vedere il funzionamento delle chiamate alle API. Per essere più chiaro possibile, descrivi gli esempi in modo molto dettagliato, per diminuire in maniera considerevole il lavoro dell'utente che dovrà provare ed usare l'API, es: ```bash $ export TOKEN=... # acquire from dashboard $ curl -is https://$TOKEN@service.com/users ``` Se usi [prmd](https://github.com/interagent/prmd) per generare la documentazione in formato Markdown, otterrai automaticamente degli esempi per ogni endpoint. #### Specifica la stabilità della tua API Specifica la stabilità della tua API oppure dei vari endpoints per quanto riguarda la maturità e la stabilità della stessa, es. tramite dei flag prototype/development/production. Dai un'occhiata a [Heroku API compatibility policy](https://devcenter.heroku.com/articles/api-compatibility-policy) per possibili cambiamenti nella stabilità o nella gestione delle policy. Una volta che la tua API è pronta per andare in produzione ed è stabile, non fare cambiamenti non retrocompatibili. Se hai bisogno di fare dei cambiamenti non retrocompatibili, crea una nuova API con un nuovo numero di versione.