From 41b7fb940c0aa967284ec93de1be8a7246e2d81a Mon Sep 17 00:00:00 2001 From: Manuel Ruhe Date: Fri, 9 Jun 2023 13:04:07 +0200 Subject: [PATCH] - link to external OTTO API Guidelines - small adjustments --- 03_api_guidelines/000_index.md | 37 ----- .../010_CORE-PRINCIPLES/010_API-design.md | 27 ---- .../020_API-as-a-product.md | 17 -- .../010_CORE-PRINCIPLES/030_API-scope.md | 23 --- .../010_CORE-PRINCIPLES/040_Contract-first.md | 18 --- .../050_Quality-standards.md | 62 ------- .../010_CORE-PRINCIPLES/060_Documentation.md | 51 ------ .../010_Basics/000_index.md | 3 - ...010_must-follow-contract-first-approach.md | 14 -- .../020_should-develop-ui-first-api-second.md | 10 -- ..._must-write-apis-using-american-english.md | 9 -- .../010_Basics/044_must-use-https.md | 11 -- ...n-is-compliant-to-openapi-specification.md | 15 -- .../050_should-involve-technical-writer.md | 9 -- .../060_may-provide-api-user-guide.md | 16 -- .../070_must-provide-contact-informaton.md | 8 - .../020_JSON/000_index.md | 1 - .../010_Naming-conventions/000_index.md | 1 - ...hould-use-camel-case-for-property-names.md | 28 ---- ...emantics-for-null-and-absent-properties.md | 27 ---- .../030_should-omit-optional-properties.md | 25 --- ...SON-objects-as-top-level-data-structure.md | 23 --- ...s-as-objects-with-keys-being-properties.md | 53 ------ .../060_should-pluralize-array-names.md | 32 ---- ...70_should-not-use-null-for-empty-arrays.md | 24 --- ...-of-fields-using-common-query-parameter.md | 18 --- ..._must-represent-enumerations-as-strings.md | 17 -- ...format-enumerations-in-upper-snake-case.md | 26 --- .../020_Canonical-data-types/000_index.md | 1 - .../010_must-use-common-data-formats.md | 77 --------- ...20_must-use-common-date-and-time-format.md | 36 ----- .../020_JSON/030_Identifiers/000_index.md | 1 - ...hould-not-use-lid-to-identify-customers.md | 11 -- ...ld-use-customerid-to-identify-customers.md | 14 -- .../030_Compatibility/000_index.md | 13 -- .../010_Compatible-changes/000_index.md | 3 - ...010_should-prefer-compatible-extensions.md | 15 -- ...0_must-not-break-backward-compatibility.md | 21 --- ...ers-to-accept-compatible-api-extensions.md | 16 -- .../040_should-use-extensible-enums.md | 48 ------ .../020_Preview/000_index.md | 3 - .../010_must-not-rely-on-preview.md | 9 -- .../030_Deprecation/000_index.md | 7 - ...proval-of-consumers-before-api-shutdown.md | 10 -- ...artner-consent-on-deprecation-time-span.md | 9 -- ...flect-deprecation-in-api-specifications.md | 20 --- ...40_must-not-start-using-deprecated-apis.md | 9 -- .../001_Contract/000_index.md | 3 - .../010_OpenAPI-specification/000_index.md | 0 ...ecification-using-openapi-for-rest-apis.md | 12 -- ...rsioning-in-openapi-specification-files.md | 21 --- .../005_Authorization/000_index.md | 1 - .../010_OAuth-2.0/000_index.md | 108 ------------- .../010_must-secure-endpoints-with-oauth2.md | 8 - .../020_must-use-authorization-grant.md | 23 --- ...ion-code-grant-for-confidential-clients.md | 8 - ...nt-for-machine-to-machine-authorization.md | 8 - ...use-pkce-for-mobile-and-javascript-apps.md | 14 -- .../060_must-not-use-implicit-grant-flow.md | 11 -- .../070_must-use-bearer-authentication.md | 18 --- .../005_Authorization/020_Scopes/000_index.md | 1 - ...-and-assign-permissions-by-using-scopes.md | 26 --- ...houd-adhere-to-scope-naming-conventions.md | 53 ------ .../005_Authorization/030_Tokens/000_index.md | 1 - .../010_must-validate-json-web-token.md | 17 -- ...validate-audience-of-the-json-web-token.md | 11 -- ..._based_on_keys in_JWKS_at_all_endpoints.md | 11 -- .../030_REST-GUIDELINES/010_HTTP/000_index.md | 1 - .../010_HTTP/010_Methods/000_index.md | 1 - .../010_must-use-http-methods-correctly.md | 117 -------------- ...0_must-fulfill-common-method-properties.md | 33 ---- ...der-to-design-post-and-patch-idempotent.md | 62 ------- ...-test-operation-for-concurrency-control.md | 38 ----- .../010_HTTP/020_Headers/000_index.md | 68 -------- ...y-use-etag-header-for-caching-resources.md | 67 -------- ...e-match-header-for-concurrrency-control.md | 95 ----------- ...etag-header-on-subsequent-modifications.md | 10 -- ...d-since-headers-for-concurrency-control.md | 16 -- ...-pattern-with-if-umodified-since-header.md | 17 -- .../010_HTTP/030_Status-codes/000_index.md | 1 - ...ust-specify-success-and-error-responses.md | 31 ---- ...020_must-use-standard-http-status-codes.md | 69 -------- ...must-use-most-specific-http-status-code.md | 8 - ...e-code-429-with-headers-for-rate-limits.md | 27 ---- .../050_must-set-user-agent.md | 14 -- .../010_HTTP/040_Caching/000_index.md | 3 - ...should-adhere-to-caching-best-practices.md | 18 --- ...t-cacheable-get-head-and-post-endpoints.md | 39 ----- ...30_should-avoid-vary-header-for-caching.md | 13 -- .../020_Hypermedia/000_index.md | 9 -- .../010_Maturity-level/000_index.md | 7 - ...10_must-implement-rest-maturity-level-2.md | 23 --- ...-maturity-level-3-for-transitional-apis.md | 35 ---- ...-hal-to-implement-REST-maturity-level-3.md | 18 --- .../020_Hypermedia/020_Links/000_index.md | 5 - .../020_Links/010_must-use-absolute-urls.md | 53 ------ ...020_should-contain-link-title-attribute.md | 22 --- .../030_must-contain-deprecation-attribute.md | 10 -- ...40_must-provide-conventional-hyperlinks.md | 74 --------- ...e-link-headers-for-json-representations.md | 10 -- .../060_must-support-forwarded-header.md | 13 -- ...ontain-separate-id-field-in-the-payload.md | 10 -- ...rmedia-controls-in-collection-resources.md | 26 --- ...st-contain-links-for-embedded-resources.md | 57 ------- ...-hypermedia-links-in-embedded-documents.md | 12 -- .../030_Link-relation-types/000_index.md | 3 - ...fer-existing-custom-link-relation-types.md | 14 -- ...fer-iana-registered-link-relation-types.md | 19 --- ...ute-urls-for-custom-link-relation-types.md | 26 --- ...040_must-use-curied-link-relation-types.md | 97 ----------- .../050_must-document-link-cardinality.md | 38 ----- .../020_Hypermedia/040_Profiles/000_index.md | 81 ---------- .../010_must-use-resolvable-profile-urls.md | 40 ----- .../020_must-use-kebab-case-profile-uris.md | 12 -- ..._must-provide-openapi-spec-for-profiles.md | 11 -- ...pe-and-profile-attributes-in-hyperlinks.md | 67 -------- .../030_Resources/000_index.md | 1 - .../010_Embedded-resources/000_index.md | 40 ----- .../010_should-embed-subresources.md | 39 ----- ...port-optional-embedding-of-subresources.md | 56 ------- ...d-resources-instead-of-traversing-links.md | 15 -- ...t-use-hal-format-for-embedded-resources.md | 14 -- .../020_Collection-resources/000_index.md | 4 - ...ust-use-plural-for-collection-resources.md | 14 -- ...-use-hal-format-for-collection-resource.md | 17 -- ...ort-pagination-for-collection-resources.md | 142 ---------------- ...must-use-common-paging-query-parameters.md | 24 --- ...should-define-default-and-max-page-size.md | 16 -- ...ge-metadata-for-offset-based-pagination.md | 29 ---- ...must-use-common-sorting-query-parameter.md | 20 --- ...arameters-for-basic-search-or-filtering.md | 37 ----- ...son-for-advanced-querying-and-filtering.md | 8 - .../030_Naming-conventions/000_index.md | 6 - ...10_must-avoid-actions-as-resource-names.md | 21 --- ...0_must-use-nouns-to-represent-resources.md | 13 -- .../030_must-use-lowercase-letters-in-uris.md | 16 -- .../040_must-follow-a-logical-order.md | 11 -- ...-to-indicate-hierarchical-relationships.md | 14 -- ..._must-not-end-uri-with-a-trailing-slash.md | 16 -- ...must-use-camelcase-for-query-parameters.md | 16 -- ...r-multiple-values-of-the-same-parameter.md | 10 -- .../090_must-use-kebabcase-for-uris.md | 13 -- ...t-use-url-friendly-resource-identifiers.md | 24 --- ...-stick-to-conventional-query-parameters.md | 59 ------- ...entifier-as-primary-resource-identifier.md | 21 --- .../040_Errors/000_index.md | 9 -- .../010_Error-handling/000_index.md | 1 - ...e-problem-json-as-error-response-format.md | 45 ------ .../020_should-use-existing-problem-types.md | 13 -- ...e-extension-for-input-validation-errors.md | 152 ------------------ ...m-extensions-by-defining-a-problem-type.md | 64 -------- .../050_Compatibility/000_index.md | 6 - .../010_Client-behavior/000_index.md | 5 - ...ust-send-unknown-fields-in-put-requests.md | 11 -- ...0_must-accept-undocumented-status-codes.md | 11 -- .../030_must-follow-redirection.md | 9 -- .../020_Versioning/000_index.md | 21 --- ..._must-use-profiles-for-public-rest-apis.md | 34 ---- ...ent-type-headers-with-profile-parameter.md | 23 --- ..._should-not-use-resource-versioned-path.md | 10 -- .../040_should-not-use-uri-versioning.md | 18 --- .../040_Deprecation/000_index.md | 3 - ...-of-deprecated-api-scheduled-for-sunset.md | 8 - ...recation-and-sunset-header-to-responses.md | 23 --- ...oring-for-deprecation-and-sunset-header.md | 10 -- .../API_error_codes.md | 0 .../README.md | 13 +- .../products-api.yml | 0 README.md | 10 +- 169 files changed, 15 insertions(+), 4023 deletions(-) delete mode 100644 03_api_guidelines/000_index.md delete mode 100644 03_api_guidelines/010_CORE-PRINCIPLES/010_API-design.md delete mode 100644 03_api_guidelines/010_CORE-PRINCIPLES/020_API-as-a-product.md delete mode 100644 03_api_guidelines/010_CORE-PRINCIPLES/030_API-scope.md delete mode 100644 03_api_guidelines/010_CORE-PRINCIPLES/040_Contract-first.md delete mode 100644 03_api_guidelines/010_CORE-PRINCIPLES/050_Quality-standards.md delete mode 100644 03_api_guidelines/010_CORE-PRINCIPLES/060_Documentation.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/000_index.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/010_must-follow-contract-first-approach.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/020_should-develop-ui-first-api-second.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/030_must-write-apis-using-american-english.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/044_must-use-https.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/045_must-ensure-implementation-is-compliant-to-openapi-specification.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/050_should-involve-technical-writer.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/060_may-provide-api-user-guide.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/070_must-provide-contact-informaton.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/000_index.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/000_index.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/010_should-use-camel-case-for-property-names.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/020_must-use-same-semantics-for-null-and-absent-properties.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/030_should-omit-optional-properties.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/040_must-always-return-JSON-objects-as-top-level-data-structure.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/050_should-represent-maps-as-objects-with-keys-being-properties.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/060_should-pluralize-array-names.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/070_should-not-use-null-for-empty-arrays.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/080_should-support-filtering-of-fields-using-common-query-parameter.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/090_must-represent-enumerations-as-strings.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/100_must-format-enumerations-in-upper-snake-case.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/000_index.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/010_must-use-common-data-formats.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/020_must-use-common-date-and-time-format.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/000_index.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/010_should-not-use-lid-to-identify-customers.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/020_should-use-customerid-to-identify-customers.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/000_index.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/000_index.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/010_should-prefer-compatible-extensions.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/020_must-not-break-backward-compatibility.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/030_must-prepare-consumers-to-accept-compatible-api-extensions.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/040_should-use-extensible-enums.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/020_Preview/000_index.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/020_Preview/010_must-not-rely-on-preview.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/000_index.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/010_must-obtain-approval-of-consumers-before-api-shutdown.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/020_must-collect-external-partner-consent-on-deprecation-time-span.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/030_must-reflect-deprecation-in-api-specifications.md delete mode 100644 03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/040_must-not-start-using-deprecated-apis.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/001_Contract/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/001_Contract/010_OpenAPI-specification/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/001_Contract/010_OpenAPI-specification/010_must-provide-api-specification-using-openapi-for-rest-apis.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/001_Contract/010_OpenAPI-specification/030_must-use-semantic-versioning-in-openapi-specification-files.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/010_must-secure-endpoints-with-oauth2.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/020_must-use-authorization-grant.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/030-should-use-authorization-code-grant-for-confidential-clients.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/040-should-use-client-credentials-grant-for-machine-to-machine-authorization.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/050_must-use-pkce-for-mobile-and-javascript-apps.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/060_must-not-use-implicit-grant-flow.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/070_must-use-bearer-authentication.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/010_must-define-and-assign-permissions-by-using-scopes.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/020_shoud-adhere-to-scope-naming-conventions.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/010_must-validate-json-web-token.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/020_must-not-validate-audience-of-the-json-web-token.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/030_must_validate_JWT_based_on_keys in_JWKS_at_all_endpoints.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/010_must-use-http-methods-correctly.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/020_must-fulfill-common-method-properties.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/030_should-consider-to-design-post-and-patch-idempotent.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/040_may-use-patch-with-json-patch-test-operation-for-concurrency-control.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/010_may-use-etag-header-for-caching-resources.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/020_should-use-etag-together-with-if-match-if-none-match-header-for-concurrrency-control.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/030_should-honor-available-etag-header-on-subsequent-modifications.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/040_should-not-use-last-modified-and-if-unmodified-since-headers-for-concurrency-control.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/050_should-follow-concurrenct-update-pattern-with-if-umodified-since-header.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/010_must-specify-success-and-error-responses.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/020_must-use-standard-http-status-codes.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/030_must-use-most-specific-http-status-code.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/040_must-use-code-429-with-headers-for-rate-limits.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/050_must-set-user-agent.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/10_should-adhere-to-caching-best-practices.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/20_must-document-cacheable-get-head-and-post-endpoints.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/30_should-avoid-vary-header-for-caching.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/010_must-implement-rest-maturity-level-2.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/020_must-implement-rest-maturity-level-3-for-transitional-apis.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/030_must-use-hal-to-implement-REST-maturity-level-3.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/010_must-use-absolute-urls.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/020_should-contain-link-title-attribute.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/030_must-contain-deprecation-attribute.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/040_must-provide-conventional-hyperlinks.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/050_must-not-use-link-headers-for-json-representations.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/060_must-support-forwarded-header.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/070_must-contain-separate-id-field-in-the-payload.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/080_must-support-hypermedia-controls-in-collection-resources.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/090_must-contain-links-for-embedded-resources.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/100_should-provide-hypermedia-links-in-embedded-documents.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/010_must-prefer-existing-custom-link-relation-types.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/020_must-prefer-iana-registered-link-relation-types.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/030_must-use-absolute-urls-for-custom-link-relation-types.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/040_must-use-curied-link-relation-types.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/050_must-document-link-cardinality.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/010_must-use-resolvable-profile-urls.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/020_must-use-kebab-case-profile-uris.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/030_must-provide-openapi-spec-for-profiles.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/040_may-use-type-and-profile-attributes-in-hyperlinks.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/010_should-embed-subresources.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/020_should-support-optional-embedding-of-subresources.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/040_should-read-embedded-resources-instead-of-traversing-links.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/050_must-use-hal-format-for-embedded-resources.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/010_must-use-plural-for-collection-resources.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/020_must-use-hal-format-for-collection-resource.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/030_must-support-pagination-for-collection-resources.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/040_must-use-common-paging-query-parameters.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/050_should-define-default-and-max-page-size.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/060_must-provide-page-metadata-for-offset-based-pagination.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/090_must-use-common-sorting-query-parameter.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/100_must-use-query-parameters-for-basic-search-or-filtering.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/110_use-json-for-advanced-querying-and-filtering.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/010_must-avoid-actions-as-resource-names.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/020_must-use-nouns-to-represent-resources.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/030_must-use-lowercase-letters-in-uris.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/040_must-follow-a-logical-order.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/050_must-use-forward-slash-to-indicate-hierarchical-relationships.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/060_must-not-end-uri-with-a-trailing-slash.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/070_must-use-camelcase-for-query-parameters.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/080_must-support-lists-for-multiple-values-of-the-same-parameter.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/090_must-use-kebabcase-for-uris.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/100_must-use-url-friendly-resource-identifiers.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/110_must-stick-to-conventional-query-parameters.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/120_should-not-use-external-identifier-as-primary-resource-identifier.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/040_Errors/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/010_must-use-problem-json-as-error-response-format.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/020_should-use-existing-problem-types.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/030_must-use-extension-for-input-validation-errors.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/040_add-custom-extensions-by-defining-a-problem-type.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/010_must-send-unknown-fields-in-put-requests.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/020_must-accept-undocumented-status-codes.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/030_must-follow-redirection.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/010_must-use-profiles-for-public-rest-apis.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/020_should-use-accept-and-content-type-headers-with-profile-parameter.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/030_should-not-use-resource-versioned-path.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/040_should-not-use-uri-versioning.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/000_index.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/010_must-monitor-usage-of-deprecated-api-scheduled-for-sunset.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/020_should-add-deprecation-and-sunset-header-to-responses.md delete mode 100644 03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/030_should-add-monitoring-for-deprecation-and-sunset-header.md rename {04_products_api => 03_products_api}/API_error_codes.md (100%) rename {04_products_api => 03_products_api}/README.md (95%) rename {04_products_api => 03_products_api}/products-api.yml (100%) diff --git a/03_api_guidelines/000_index.md b/03_api_guidelines/000_index.md deleted file mode 100644 index b34923c..0000000 --- a/03_api_guidelines/000_index.md +++ /dev/null @@ -1,37 +0,0 @@ -# OTTO API Guidelines - -Our APIs are a valuable part of our business assets, as with APIs we generate the corresponding operating values. -Ideally, by applying the API guidelines, all APIs look as if they were created by a single team, thus providing API consumers with a homogeneous, easy-to-use product. -This facilitates a great developer experience and the ability to quickly compose complex business processes. - -With this in mind, we trust that our teams build APIs that are: - -- self-explanatory -- easy to use and robust -- of high quality -- consistent -- transparently versioned -- RESTful with respect to REST APIs - -## How to read the guidelines - -This guide is a living document and will be revised over time as new rules are added or existing rules are modified. - -The guidelines are structured into individual rules that use the key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY". -These keywords are to be interpreted as described in [RFC2119](https://www.ietf.org/rfc/rfc2119.txt). -In this document, such keywords are highlighted at the beginning of each section in uppercase letters and are color-coded. - -Disclaimer -Code examples may be incomplete and/or may violate the rules described in the guidelines. Examples are intentionally kept simple to make them more accessible and easier to comprehend. They are always correct in their context, but not necessarily outside of it. - -Common examples for this are: - -- omitted headers such as `Authorization` -- omitted (mandatory) properties in JSON responses - -## Attribution - -At this point we would like to send Kudos to Zalando SE whose Tech Team did a great job crafting the [Zalando RESTful API Guidelines](https://opensource.zalando.com/restful-api-guidelines/#). -As much of the content resonates with what we do at OTTO, their well-prepared document inspired us and in certain parts provided a basis when crafting the OTTO API Guidelines. - -The Zalando RESTful API Guidelines are published under the [Creative Commons Attribution 4.0 International License](https://github.com/zalando/restful-api-guidelines/blob/main/LICENSE) (CC BY 4.0). For further notes on these OTTO API Guidelines’ license under CC BY 4.0, please refer to the [Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/legalcode). diff --git a/03_api_guidelines/010_CORE-PRINCIPLES/010_API-design.md b/03_api_guidelines/010_CORE-PRINCIPLES/010_API-design.md deleted file mode 100644 index 83a0392..0000000 --- a/03_api_guidelines/010_CORE-PRINCIPLES/010_API-design.md +++ /dev/null @@ -1,27 +0,0 @@ -# API design - -API design involves many aspects such as architectural styles, API governance, backend capabilities, performance, and such. -There are many constraints and compromises to be considered. -With our API design we want to create value for the customer and provide a good developer experience. - -## REST APIs - -For our REST APIs, we've decided to apply the RESTful principle to all kind of application components. -REST resources are identified via URIs and can be manipulated via standardized CRUD operations using different representations, and hypermedia. -RESTful APIs come with less rigid client/server coupling and are more suitable for an ecosystem of (core) services providing a platform of APIs to build diverse business services. - -In summary: - -- We prefer REST-based APIs with JSON payloads. -- We prefer systems to be truly RESTful. - -References: -- [Build APIs You Won’t Hate](https://www.amazon.de/Build-APIs-You-Wont-Hate/dp/0692232699) -- [Irresistable APIs: Designing web APIs that developers will love](https://www.amazon.de/Irresistible-APIs-Designing-that-developers/dp/1617292559) -- [Architectural Styles and the Design of Network-Based Software Architectures](https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm) - -## Asynchronous APIs - -With our asynchronous APIs, we aim for low coupling between services, i.e. to remove the need for services to actively send queries via synchronous APIs. -This reduces latency and simplifies changing services in insolation. -By using events, we provide a mechanism, that allows consumers to subscribe to events of their interest, whereas we use commands for actions to be executed by a specific recipient. diff --git a/03_api_guidelines/010_CORE-PRINCIPLES/020_API-as-a-product.md b/03_api_guidelines/010_CORE-PRINCIPLES/020_API-as-a-product.md deleted file mode 100644 index baecea4..0000000 --- a/03_api_guidelines/010_CORE-PRINCIPLES/020_API-as-a-product.md +++ /dev/null @@ -1,17 +0,0 @@ -# API as a product - -When looking at APIs, the focus is mostly on the technical implementation, whereas the business perspective is often overlooked. -But exactly in the business context more and more services are being created. -Therefore, we need to understand our API as a product and not just look at it as a pure code base. -Just like any other product, our API has consumers, it is subject to continuous development, it strives for high quality standards, and flexible delivery of features. -In addition, an API needs to deliver value such as efficiency and scalability, a flexible business model, shorter time to market, as well as lower development and maintenance costs. - -From a business perspective, every API transaction has a value, whether it is data generation, integrating with third-parties, or direct revenue generation. -We treat our API as a business value generator that gives API consumers a great experience to integrate with, while at the same time generating revenue. - -Hence, the design of our APIs is based on the "API as a product" principle: - -- Our API is a product and we are responsible for it. -- We provide our consumers with a homogeneous, easy-to-use API. -- We advocate for our user's needs. -- We actively improve and maintain API consistency. diff --git a/03_api_guidelines/010_CORE-PRINCIPLES/030_API-scope.md b/03_api_guidelines/010_CORE-PRINCIPLES/030_API-scope.md deleted file mode 100644 index e42f895..0000000 --- a/03_api_guidelines/010_CORE-PRINCIPLES/030_API-scope.md +++ /dev/null @@ -1,23 +0,0 @@ -# API scope - -APIs can be assigned attributes to define certain non-functional requirements. -Here's what this exactly means in the context of the OTTO API. - -Basically APIs can be described with the following attributes: - -| Attribute | Description | -| --------- | --------------------------------------------------------------------------------------------------------------- | -| public | No network access restrictions, world-wide reachable. | -| private | Network access restrictions, e.g. firewall or egress SecurityGroups required. | -| open | No authorization/authentication required, anonymous access. | -| closed | Authorization/authentication required, different scopes for fine-grained permissions. | -| published | Service Level Agreements apply, such as established versioning, changelog, and documentation processes. | -| internal | Less strict Service Level Agreements, such as no established versioning, changelog, or documentation processes. | - -The scope of the OTTO API ranges between a public and a private API. -The operational and organisational requirements such as guidelines, governance, documentation, and stability are similar to those of a public API. -The scope, level of detail, and content of the endpoints are not intended for public or anonymous use. -Access to data and company assets is only granted to selected and predictable API consumers. -This approach enables a targeted and managed development of API clients and products. - -The OTTO API corresponds to the attributes **public**, **closed**, and **published**. diff --git a/03_api_guidelines/010_CORE-PRINCIPLES/040_Contract-first.md b/03_api_guidelines/010_CORE-PRINCIPLES/040_Contract-first.md deleted file mode 100644 index fcb3471..0000000 --- a/03_api_guidelines/010_CORE-PRINCIPLES/040_Contract-first.md +++ /dev/null @@ -1,18 +0,0 @@ -# Contract first - -There are repeated discussions about the "API First" development paradigm, and many well-known software development companies follow this approach. -The definition and understanding are not consistent though, and we have learned that the "API First" approach does not work well for us. -But "Contract First" does even better. - -In a nutshell, Contract First implies that we start out establishing a contract and then share it with our consumer. -The contract includes what the request and response communication is expected to be. -Once the contract is in place, the backend team can start developing the API whereas the consumer can start working on an application to consume it. - -Specifically we have decided to follow the principle "UI First, API Second" based on some thoughts that [Stefan Tilkov posted on Twitter](https://twitter.com/stilkov/status/1250355396864176132). -This implies that we do not approach the API design from the backend point of view, but from the direction of a specific visual representation of the intended feature. - -What are the advantages of Contract First for us? - -- Since coding happens based on the contract, the backend team and the consumer are clear about the communication approach and details. Hence, development on backend and consumer side can happen at the same time. - -- The backend team and the consumer have an idea of each others' expectations. As a result, if cross-team testing is not possible due to different paces of development, stub software can be used to mock the other's behavior, all based on the contract. diff --git a/03_api_guidelines/010_CORE-PRINCIPLES/050_Quality-standards.md b/03_api_guidelines/010_CORE-PRINCIPLES/050_Quality-standards.md deleted file mode 100644 index f01164d..0000000 --- a/03_api_guidelines/010_CORE-PRINCIPLES/050_Quality-standards.md +++ /dev/null @@ -1,62 +0,0 @@ -# Quality standards - -As already mentioned, [the scope of the OTTO API](./030_API-scope.md) ranges between a public and a private API. -Nevertheless, when it comes to quality, we strive for the standards of a public API. -If our API needs to be public by tomorrow, external users should then be able to consume our API immediately. -What's more, a consistent understanding of quality standards facilitates the development of further endpoints and the evolution of the OTTO API as a product without unnecessary consultation between all parties involved. - -Our understanding of quality covers the following aspects: - -## Robustness -All implementations of our API follow the [Robustness Principle](https://en.wikipedia.org/wiki/Robustness_principle), as it is essential for the evolution of APIs. -Future changes to interfaces cannot be anticipated in advance, so aspects such as backward compatibility, loose coupling, and the elimination of the need to synchronize different services are of crucial importance. -This is especially applicable for microservice environments where dependencies between services should be kept to a minimum. - -Be conservative in what you do, be liberal in what you accept from others. - -## Consistency -Our API is essentially developed by independent, autonomous functional teams. -However, we strive for a uniform presentation to the outside world. -The API should give the impression that it was developed by a single team. -This consistency covers several facets such as documentation, naming conventions, code examples, common data structures, pagination, governance, authentication, and error codes. - -## Reliability -If our API infrastructure is not reliable, consumers will not build trust, and engagement will not increase. -API reliability extends beyond uptime. -We do not limit our evaluation to availability, but also include aspects such as fluctuations in response times or behavior with an increasing number of concurrent API clients. - -We avoid unannounced changes and prevent outages to the best of our knowledge. -When having to choose between consistency (always return even in case of an error) and availability (in doubt return stale content), we prefer availability. Even to the detriment of consistency. -Our endpoints must always return a response, whether the requested operation succeeds or fails. - -## Security -Security is not a marginal topic, but an integral part of all software projects, and thus also of APIs. - -Not all vulnerabilities will be preventable. -However, a good rule of thumb is to prepare for the worst case scenario that everyone is out to get our data. -We leverage industry-standard technologies for encryption, authentication, and authorization. - -We are conservative in exposing our data and the [Principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) is applied to allow API clients only enough access to perform the required tasks. -In addition, we strive to include only the least amount of data necessary to respond to any API call and secure our applications against the [OWASP Top 10 Threats](https://owasp.org/www-project-top-ten/). - -We also restrict the rate limit to specific resources to prevent misuse. - -## Performance -We identify and analyze key metrics for different groups of interest. -The bandwidth of possible metrics ranges from purely technical information such as uptime, latencies, and error rates to business insights such as SDK, version adoption, as well as Time to First Hello World (TTFHW), or API usage growth. - -## Documentation & Support -We help both vendors during development and users of our API with the integration by offering suitable ways of exchange and support. -As the primary resource for explaining our API and its capabilities, documentation must be as accessible to the audience as possible. -We provide all consumers of our API with comprehensive, professional, up-to-date, and complete information. - -## Communication -We always keep both developers and consumers of our API informed through appropriate channels. -Changes and [deprecations](../030_REST-GUIDELINES/050_Compatibility/040_Deprecation/000_index.md) are communicated regularly and actively. -Therefore, we establish different synchronous and asynchronous communication channels to support developers and consumers. - -## Developer Experience -API consumers should have fun using our API. -Our goal is to provide seamless experience to developers when writing software, and to increase their efficiency. -API consumers should be comfortable using our API in their programming language of choice, finding the functionality they need, as well as using the output. -We give developers the right tools to help them succeed and aim to provide an as short as possible TTFHW. diff --git a/03_api_guidelines/010_CORE-PRINCIPLES/060_Documentation.md b/03_api_guidelines/010_CORE-PRINCIPLES/060_Documentation.md deleted file mode 100644 index 8c6eacf..0000000 --- a/03_api_guidelines/010_CORE-PRINCIPLES/060_Documentation.md +++ /dev/null @@ -1,51 +0,0 @@ -# Documentation - -Our [quality standards](./050_Quality-standards.md) define all the values that are important to us. -What's more, we aim to take care of clearly structured documentation, provide our audience with code examples, and make sure they have a great time using our API. -Here's what that means: - -## Clear structure -**Usability** - -- A user-friendly navigation makes it easy to discover the API and find all relevant information. -- The sidebar is cleary structured and easy to navigate. -- API endpoints and examples are shown in context. - -**Getting started** - -- Basic information is available at one central place, such as info about HTTP methods, API operations, request/response headers, versioning, pagination, or errors. -- A short and simple guide provides an overview of the most likely tasks to perform with the API. -- Users can get in touch with us via a contact form. - -**Tutorials** -With step-by-step walkthroughs we'll cover specific functionality that can be implemented with the API. - -**Familiarize users with the API** -We'll cater for experienced users that already have an idea of the endpoints to be used, and at the same time provide the respective structure and information for inexperienced users who need a thorough introduction and/or example use cases. - -**Discoverable and easy to digest** - -- All information is easily discoverable, easy to digest, and prepared in a way that the user can effectively work with it. -- We'll be consistent with our tone of voice, terminology, attribute names, API endpoint design, requests and responses, and counting. -- The layout supports accordingly, e.g. with syntax highlighting or multi-column layout. - -## Code examples -**Default values** -Request and response examples that belong to every endpoint documentation have meaningful default values that follow a specific story. - -**Code examples and schemas** -Every endpoint documentation comes with examples and also provides schemas listing the available attributes with explanatory text. - -**Automated API reference documentation** -API reference documentation is created and published automatically, see [MUST provide API specification using OpenAPI](@guidelines/R000003). - -## Consistency and accessibility - -- Documentation is provided in American English (EN-US), as US spelling has become the standard in APIs. Also endpoints, properties, and default values are provided in American English. -- Users can search the documentation. -- The sidebar is available at all times so that the documentation can be easily browsed. All the endpoints can be accessed via the sidebar. -- Code examples and explanatory text are visually separated. - -## Efficient and refined -The API is well-documented and up-to-date. -Users can flawlessly integrate and are informed about recent changes via a revision history. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/000_index.md b/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/000_index.md deleted file mode 100644 index de8c5bd..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/000_index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Basics - -This section contains basic rules and concepts that lay the groundwork for API type-specific rules. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/010_must-follow-contract-first-approach.md b/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/010_must-follow-contract-first-approach.md deleted file mode 100644 index dcae353..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/010_must-follow-contract-first-approach.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -type: MUST -id: R000001 ---- - -# follow Contract First approach - -When a new API is being developed, we follow the [Contract First approach](../../../010_CORE-PRINCIPLES/040_Contract-first.md). -This requires the following aspects: - -- We define API contracts first before coding the implementation using a [standard specification language](@guidelines/R000003). -- We get early review feedback from peers and API consumers. - -By defining API contracts outside of the code, we aim to facilitate early review feedback and a development discipline that focuses service interface design on a profound understanding of the domain and the required functionality. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/020_should-develop-ui-first-api-second.md b/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/020_should-develop-ui-first-api-second.md deleted file mode 100644 index 5343bb4..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/020_should-develop-ui-first-api-second.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -type: SHOULD -id: R000002 ---- - -# develop UI first, API second - -While the development of additional endpoints is crucial to establish a comprehensive and vital API ecosystem, we do not want to build endpoints upfront without the appropriate use cases. -In a first step, you should focus on implementing an appropriate UI to identify the requirements and quality factors of the API. -Only in a second step, we provide an API, that is suitable to implement more clients, having similar requirements as the first UI use case. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/030_must-write-apis-using-american-english.md b/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/030_must-write-apis-using-american-english.md deleted file mode 100644 index 43f0a2d..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/030_must-write-apis-using-american-english.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -type: MUST -id: R000004 ---- - -# write APIs using American English - -The API description as well as the overall documentation must be written in American English. -We use standard American spelling. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/044_must-use-https.md b/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/044_must-use-https.md deleted file mode 100644 index 2b45f62..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/044_must-use-https.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -type: MUST -id: R000046 -reviewType: automatic ---- - -# use TLS - -All API communication must be secured via Transport Level Security (TLS) formerly known as Secure Sockets Layer (SSL). - -This means that HTTP communication must be made over TLS, resulting in HTTPS communication. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/045_must-ensure-implementation-is-compliant-to-openapi-specification.md b/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/045_must-ensure-implementation-is-compliant-to-openapi-specification.md deleted file mode 100644 index 2fa6b14..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/045_must-ensure-implementation-is-compliant-to-openapi-specification.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -type: MUST -id: R000076 ---- - -# ensure implementation complies with the contract - -The contract defined in the specification (i.e. OpenAPI or AsyncAPI) is binding. -API providers must ensure that the implementation complies with the agreed specification. -Ideally, compliance tests are part of the build pipeline. - -Use - -- unit tests to validate the API against the specification -- Consumer Driven Contract (CDC) tests for a more inclusive and consumer-oriented approach. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/050_should-involve-technical-writer.md b/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/050_should-involve-technical-writer.md deleted file mode 100644 index faf89eb..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/050_should-involve-technical-writer.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -type: SHOULD -id: R000006 ---- - -# involve technical writer - -Any description that has been provided by developers in the OpenAPI specification should undergo a copy editing and proofreading process by a technical writer. -As explanations may be too difficult for the audience to understand, may not be sufficiently described or may contain inconsistent terminology, all texts should be edited by a technical writer. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/060_may-provide-api-user-guide.md b/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/060_may-provide-api-user-guide.md deleted file mode 100644 index 814ee36..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/060_may-provide-api-user-guide.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -type: MAY -id: R000005 ---- - -# provide API user guide - -In order to improve the developer experience of API consumers, especially of engineers that are less experienced in using the OTTO API, it is good practice to provide an API user guide along with the API reference (provided via the API spec). -A helpful API user guide typically describes aspects such as: - -- API scope, purpose, and use cases -- Concrete examples of API usage -- Error handling information and solution support -- Architectural context and major dependencies, including illustrations and flow charts - -The user guide is created by a [technical writer](R000006) in a central repository, agreed with the development teams, and published online together with the API reference. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/070_must-provide-contact-informaton.md b/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/070_must-provide-contact-informaton.md deleted file mode 100644 index 06b3e12..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/010_Basics/010_Basics/070_must-provide-contact-informaton.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -type: MUST -id: R000078 ---- - -# provide contact information - -An API contract must contain the contact information of the team owning the respective specification. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/000_index.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/000_index.md deleted file mode 100644 index 02ed5a2..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# JSON diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/000_index.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/000_index.md deleted file mode 100644 index cbec012..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# Naming conventions diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/010_should-use-camel-case-for-property-names.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/010_should-use-camel-case-for-property-names.md deleted file mode 100644 index 3b253f0..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/010_should-use-camel-case-for-property-names.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -type: SHOULD -id: R004010 ---- - -# use camelCase for property names - -Property names of JSON objects should be formatted in camelCase. - -DO - -````json -{ - "name": "John", - "jobDescription": "product manager", - "vacationDays": 37 -} -```` - -DON'T - -````json -{ - "NAME": "John", - "job-description": "product manager", - "vacationdays": 37 -} -```` diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/020_must-use-same-semantics-for-null-and-absent-properties.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/020_must-use-same-semantics-for-null-and-absent-properties.md deleted file mode 100644 index 66db1a5..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/020_must-use-same-semantics-for-null-and-absent-properties.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -type: MUST -id: R004020 ---- - -# use same semantics for null and absent properties - -If a property is `nullable` and `not required`, a property `null` value and an absent property must be considered semantically equivalent. - -So this object with `null property value`: - -```json -{ - "name": "John", - "age": null -} -``` - -should be considered semantically equivalent to this object with `absent property`: - -```json -{ - "name": "John" -} -``` - -`Note`{ label } `PATCH` endpoints are an exception to this rule (see [MUST use HTTP methods correctly](R000007)). Regarding the example above, a `PATCH` request with the first object would set the `name` to `John` and the `age` to `null`, whereas a request with the second object would only modify the `name`. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/030_should-omit-optional-properties.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/030_should-omit-optional-properties.md deleted file mode 100644 index aad4f9f..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/030_should-omit-optional-properties.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -type: SHOULD -id: R004021 ---- - -# omit optional properties - -Although [null and absent properties are semantically equivalent](R004020), optional properties should be omitted instead of null whenever applicable. - -DO - -```json -{ - "paymentMethod": "INVOICE_SINGLE" -} -``` - -DON'T - -```json -{ - "paymentMethod": "INVOICE_SINGLE", - "installments": null -} -``` diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/040_must-always-return-JSON-objects-as-top-level-data-structure.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/040_must-always-return-JSON-objects-as-top-level-data-structure.md deleted file mode 100644 index ed64511..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/040_must-always-return-JSON-objects-as-top-level-data-structure.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -type: MUST -id: R004030 -reviewType: automatic ---- - -# always return JSON objects as top-level data structure - -The top-level data structure of your JSON response should always be a JSON object and not, for example, an array. - -DO - -```json -{ - "searchSuggestions": ["gaming pc", "gaming laptop", "gaming monitor"] -} -``` - -DON'T - -```json -["gaming pc", "gaming laptop", "gaming monitor"] -``` diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/050_should-represent-maps-as-objects-with-keys-being-properties.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/050_should-represent-maps-as-objects-with-keys-being-properties.md deleted file mode 100644 index 1c836a3..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/050_should-represent-maps-as-objects-with-keys-being-properties.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -type: SHOULD -id: R004040 ---- - -# represent maps as objects with keys being their property names - -Strive to model your schema consumer-agnostic. That implies: - -- don't expect your consumer to use a certain technology, library or framework -- don't fulfill consumer-specific requirements such as indexing data, as other consumers have different requirements. - -DON'T - -```json -{ - "availableVariantsByColor": [ - { - "key": "red", - "value": ["L", "XL"] - }, - { - "key": "blue", - "value": ["S", "XL"] - }, - { - "key": "green", - "value": ["L"] - } - ] -} -``` - -This example violates both of the above rules because: - -- the data is grouped by color. Another consumer might require the data to be grouped by size -- the dictionary representation of data uses a custom meta-schema instead of native json objects. - -DO - -```json -{ - "availableVariants": [ - { "color": "red", "size": "L" }, - { "color": "red", "size": "XL" }, - { "color": "blue", "size": "S" }, - { "color": "blue", "size": "XL" }, - { "color": "green", "size": "L" } - ] -} -``` - -If the consumer is not able to create a backend for the frontend, the API provider can provide a subresource e.g. `[...]/available-variants`, which allows filtering and sorting in different ways. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/060_should-pluralize-array-names.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/060_should-pluralize-array-names.md deleted file mode 100644 index 1591555..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/060_should-pluralize-array-names.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -type: SHOULD -id: R004050 ---- - -# pluralize array names - -Arrays should have pluralized names whereas objects should be named in singular. - -DO - -````json -{ - "imageData": { - "imageBrand": "i.otto.de/i/otto/2212", - "imageShop": "i.otto.de/i/otto/86" - }, - "keys": ["ffe6372af30", "d8e6372af40"] -} -```` - -DON'T - -````json -{ - "images": { - "imageBrand": "i.otto.de/i/otto/2212", - "imageShop": "i.otto.de/i/otto/86" - }, - "keyCollection": ["ffe6372af30", "d8e6372af40"] -} -```` diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/070_should-not-use-null-for-empty-arrays.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/070_should-not-use-null-for-empty-arrays.md deleted file mode 100644 index 0e34dff..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/070_should-not-use-null-for-empty-arrays.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -type: SHOULD NOT -id: R004060 ---- - -# use null for empty arrays - -Arrays should be empty and not null if there is no data to provide. - -DO - -````json -{ - "entries": [] -} -```` - -DON'T - -````json -{ - "entries": null -} -```` diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/080_should-support-filtering-of-fields-using-common-query-parameter.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/080_should-support-filtering-of-fields-using-common-query-parameter.md deleted file mode 100644 index dbe89ed..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/080_should-support-filtering-of-fields-using-common-query-parameter.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -type: SHOULD -id: R004070 ---- - -# support filtering of fields using common query parameter - -To reduce potential load on the server and reduce the payload size, you can use the `fields` query parameter to specify the set of properties you are interested in and that will be included in the response. -You should also support filtering of nested properties. - -Examples: - -- `fields=(name)`: include only field `name` -- `fields=(name,id)`: include field `name` and `id` -- `fields=(name,friends(id,name))`: include field `name` and `friends`, with `friends` only having `id` and `name` properties - -References: -- [MUST stick to conventional query parameters](R000049) diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/090_must-represent-enumerations-as-strings.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/090_must-represent-enumerations-as-strings.md deleted file mode 100644 index 469a98a..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/090_must-represent-enumerations-as-strings.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -type: MUST -id: R004080 ---- - -# represent enumerations as strings - -An enumeration is a human readable representation of data. -Therefore, strings are a good data type choice for enumerations. - -Example: - -````json -{ - "clientStatus": "NOT_ACTIVE" -} -```` diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/100_must-format-enumerations-in-upper-snake-case.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/100_must-format-enumerations-in-upper-snake-case.md deleted file mode 100644 index a61aa49..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/010_Naming-conventions/100_must-format-enumerations-in-upper-snake-case.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -type: MUST -id: R004090 ---- - -# format enumerations in UPPER_SNAKE_CASE - -In order to easily distinguish between values and properties, it is best practice to write enumerations in UPPER_SNAKE_CASE format. - -DO - -````json -{ - "eventType": "EMAIL", - "clientStatus": "STOPPED_AFTER_ERROR" -} -```` - -DON'T - -````json -{ - "eventType": "Email", - "clientStatus": "stoppedAfterError" -} -```` diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/000_index.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/000_index.md deleted file mode 100644 index 8179ad8..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# Canonical data types diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/010_must-use-common-data-formats.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/010_must-use-common-data-formats.md deleted file mode 100644 index 9e8a6ea..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/010_must-use-common-data-formats.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -type: MUST -id: R100071 ---- - -# use common data formats - -Use standard data formats as defined in - -- [OpenAPI Specification: Data Types](http://spec.openapis.org/oas/v3.0.3#data-types) -- [JSON Schema: Built-in formats](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.7.3) - -The following is a non-exhaustive table of common formats. - -Format names starting with `otto:` are not defined by OpenAPI or JSON Schema and are specific to the OTTO organisation. -They represent formats that are not covered or are extensions of existing ones. - -| type | format | spec | example | comment | | -| ------- | --------------------- | -------------------------------------- | -------------------------------------- | ------------------------------- | --------------------------- | -| integer | int32 | | | signed 32 bits | -| integer | int64 | | | | signed 64 bits (a.k.a long) | -| number | float | | | | | -| number | double | | | | | -| string | | | | | | -| string | byte | | | base64 encoded characters | | -| string | binary | | | any sequence of octets | | -| boolean | | | | | | -| string | date | [RFC3339] - `full-date` | `2020-06-16` | see also [date rule][rule-date] | | -| string | date-time | [RFC3339] - `date-time` | `2020-06-16T04:05:06Z` | see also [date rule][rule-date] | | -| string | time | [RFC3339] - `full-time` | `04:05:06Z` | see also [date rule][rule-date] | | -| string | duration | [RFC3339] - `duration` | `P1DT12H` (1 day 12 hours) | | | -| string | password | | `passw0rd` | a hint for processing/display | | -| string | email | [RFC5322][rfc5322] | `example@example.com` | internationalized email | | -| string | idn-email | [RFC5322][rfc5322] | | | | -| string | hostname | [RFC1123][rfc1123], [RFC5891][rfc5891] | `www.otto.de` | internationalized hostname | | -| string | idn-hostname | [RFC1123][rfc1123], [RFC5890][rfc5890] | | | | -| string | ipv4 | [RFC2673][rfc2673] | `127.0.0.1` | | | -| string | ipv6 | [RFC2673][rfc2673] | `0:0:0:0:0:0:0:1` | | | -| string | uri | [RFC3986][rfc3986] | `http://otto.de` | | | -| string | uri-reference | [RFC3986][rfc3986] | | | | -| string | uri-template | [RFC6570][rfc6570] | `http://api.otto.de/users/{userId}` | | | -| string | iri | [RFC3987][rfc3987] | | internationalized URI | | -| string | iri-reference | [RFC3987][rfc3987] | | internationalized URI-reference | | -| string | uuid | [RFC4122][rfc4122] | `f81d4fae-7dec-11d0-a765-00a0c91e6bf6` | | | -| string | json-pointer | [RFC6901][rfc6901] | `/foo/0` | | | -| string | relative-json-pointer | [DRAFT json-pointer][json-pointer] | `1/nested/objects` | | | -| string | regex | [ECMA-262][ecma-262] | `[a-f]+[0-9]*` | | | -| string | otto:country-code | [ISO 3166-1-alpha2][iso3166-1-alpha2] | `DE`, `GB` | | | -| string | otto:language-code | [ISO 639-1][iso639-1], [BCP 47][bcp47] | `de`, `de-DE`, `en`, `en-US` | | | -| string | otto:currency-code | [ISO 4217][iso4217] | `EUR`, `USD`, `CHF` | | | - -These format names are intended to be used in the OpenAPI specification provided by the service. - - -References: -- [MUST provide API specification using OpenAPI](@guidelines/R000003) -- [MUST provide OpenAPI specification for profiles](@guidelines/R100067) - -[rule-date]: ./020_must-use-common-date-and-time-format.md -[rfc3339]: https://tools.ietf.org/html/rfc3339#section-5.6 -[rfc5322]: https://tools.ietf.org/html/rfc5322#section-3.4.1 -[rfc6531]: https://tools.ietf.org/html/rfc6531 -[rfc1123]: https://tools.ietf.org/html/rfc1123#section-2.1 -[rfc5891]: https://tools.ietf.org/html/rfc5891#section-4.4 -[rfc5890]: https://tools.ietf.org/html/rfc5890#section-2.3.2.3 -[rfc2673]: https://tools.ietf.org/html/rfc2673#section-3.2 -[rfc3986]: https://tools.ietf.org/html/rfc3986 -[rfc3987]: https://tools.ietf.org/html/rfc3987 -[rfc6901]: https://tools.ietf.org/html/rfc6901#section-5 -[json-pointer]: https://tools.ietf.org/html/draft-handrews-relative-json-pointer-02 -[ecma-262]: https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf -[rfc6570]: https://tools.ietf.org/html/rfc6570 -[rfc4122]: https://tools.ietf.org/html/rfc4122 -[iso3166-1-alpha2]: https://www.iso.org/iso-3166-country-codes.html -[iso639-1]: https://www.loc.gov/standards/iso639-2/php/English_list.php -[bcp47]: https://tools.ietf.org/html/bcp47 -[iso4217]: https://www.currency-iso.org/en/home/tables/table-a1.html diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/020_must-use-common-date-and-time-format.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/020_must-use-common-date-and-time-format.md deleted file mode 100644 index 917999a..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/020_Canonical-data-types/020_must-use-common-date-and-time-format.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -type: MUST -id: R100072 ---- - -# use common date and time format - -Use the `full-date`, `date-time` or `full-time` format as defined in [RFC3339][rfc3339]. - -Examples: - -`full-date`: - -- `2020-06-16` -- `1986-12-01` - -`date-time`: - -- `2020-06-16T04:05:06Z` -- `2020-10-05T11:23:09+02:00` -- `1986-12-01T05:12:55.12Z` - -Use `date-time` in UTC without time zone (e.g. `2020-06-16T12:53:11Z`). - -In the [OpenAPI specification][openapi-specification-data-types] `full-date` corresponds to `date`, `date-time` corresponds to `date-time`. -In the [JSON Schema specification][json-schema-spec-defined-formats] `full-time` corresponds to `time`. - -HTTP headers must use the date format recommended by the HTTP specification [RFC7231][rfc7231] (e.g. `Sun, 06 Nov 1994 08:49:37 GMT`). - -References: -- [MUST use common data formats](@guidelines/R100071) - -[rfc3339]: https://tools.ietf.org/html/rfc3339#section-5.6 -[json-schema-spec-defined-formats]: https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.7.3 -[openapi-specification-data-types]: http://spec.openapis.org/oas/v3.0.3#data-types -[rfc7231]: https://tools.ietf.org/html/rfc7231#section-7.1.1.1 diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/000_index.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/000_index.md deleted file mode 100644 index 326718a..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# Identifiers diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/010_should-not-use-lid-to-identify-customers.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/010_should-not-use-lid-to-identify-customers.md deleted file mode 100644 index 9f1999f..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/010_should-not-use-lid-to-identify-customers.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -type: SHOULD NOT -id: R100074 ---- - -# use lId (or loginId) to identify customers - -The lId (or loginId) was introduced for one specific, limited usecase and is a suboptimal way to identify logged in customers. -On a technical level one customer can have a multitude of different lIds. - -It is also not trivially possible for endpoints or clients derive the customer the lId refers to without knowledge of a common secret which is privileged knowledge. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/020_should-use-customerid-to-identify-customers.md b/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/020_should-use-customerid-to-identify-customers.md deleted file mode 100644 index 59b6b64..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/020_JSON/030_Identifiers/020_should-use-customerid-to-identify-customers.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -type: SHOULD -id: R100078 ---- - -# use customerId to identify customers - -The `customerId` is the recommended way to identify logged in customers. It replaces the `ec-uuid`. - -In HTTP headers, the `customerId` should be named consistently `X-Customer-Id`. - -For the time being, the `sub`-claim of the JWT still contains the `ec-uuid` for tokens granted through the [authorization code grant flow](R000052). - -An example is provided in the [OAuth2 section](../../../030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/000_index.md). diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/000_index.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/000_index.md deleted file mode 100644 index e8f9ddf..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/000_index.md +++ /dev/null @@ -1,13 +0,0 @@ -# Compatibility - -As long as applications are used, they are subject to change. As applications change, it is likely that the APIs they use or provide will also change occasionally. So that in a distributed system landscape not all applications involved in a communication via an API have to be updated at the same time, it is important to keep changes to the API as transparent as possible for all parties involved in the communication. _Transparency_ in this context means that despite the change, the existing communication parties can continue to communicate without any problems even with the partners who have already implemented the change. - -According to this definition, the term _compatibility_ refers solely to the exchange of messages _on the wire_. Further interpretations, such as the API's specification file itself and its possible processing on the tool side (e.g. code generators), are explicitly excluded. However, API providers are of course free to give their consumers further guarantees that go beyond compatibility _on the wire_. - -This section deals with topics, such as [compatible API evolution](./010_Compatible-changes/000_index.md), introduction of [new API components](./020_Preview/000_index.md) and finally retiring [obsoleted API components](./030_Deprecation/000_index.md). - -The general rules for compatibility included in this section are independent of the API type. -Versioning and other compatibility rules specific to REST and Event APIs are documented in their respective sections: - -- [Compatibility for REST APIs](../../030_REST-GUIDELINES/050_Compatibility/000_index.md) -- [Compatibility for Event APIs](../../040_EVENT-GUIDELINES/050_Compatibility/index.md) diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/000_index.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/000_index.md deleted file mode 100644 index 451cdcf..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/000_index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Compatible changes - -Changing existing APIs in a compatible way makes it easier for both API providers and consumers. Providers will have fewer API versions to maintain, while consumers have less need to migrate to a new API version. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/010_should-prefer-compatible-extensions.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/010_should-prefer-compatible-extensions.md deleted file mode 100644 index 16bf8cb..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/010_should-prefer-compatible-extensions.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -type: SHOULD -id: R000028 ---- - -# prefer compatible extensions - -API providers should always prefer to extend APIs in a compatible way. The following rules provide guidance on how to evolve APIs in a backward-compatible way: - -- Refer to [best practices (internal link)](https://github.com/otto-ec/ottoapi_guidelines/blob/main/content/references/REST/compatibility.md)] when adding new fields -- Never change the semantic of fields (e.g. changing the semantic from customer-number to customer-id, as both are different unique customer keys) -- Input fields may have constraints (e.g. patterns, formats, lengths or business rules, if any are documented alongside the spec) being validated via server-side logic. Never change the validation logic to be more restrictive and make sure that all constraints are clearly explained in the spec documentation and error response description. -- Enum ranges can be reduced when used as input parameters only if the server is ready to accept and process old range values as well. However, a 422 validation error response with an indication of why the old value is no longer accepted is fine. The enum range can be reduced if it is used as an output parameter. -- Enum ranges should not be extended when used for output parameters. Clients often interpret the enum type as a closed set of values and might break when receiving new values. However, enum ranges can be extended when used for input parameters. -- Use extensible enums if enums are likely to be extended due to business requirements (see [SHOULD use extensible enums](@guidelines/R000035)). diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/020_must-not-break-backward-compatibility.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/020_must-not-break-backward-compatibility.md deleted file mode 100644 index 91b62d8..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/020_must-not-break-backward-compatibility.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -type: MUST NOT -id: R000027 ---- - -# break backward compatibility - -API specifications establish a contract between providers and consumers and cannot be broken by unilateral decisions. -Providers can change their API specifications, but have to ensure their changes won't break existing consuming clients. -Consumers usually have independent release cycles for their clients, focusing more on stability and avoiding changes that do not add value. - -There are two ways to change APIs without breaking them: - -- Follow the rules for compatible extensions. -- Introduce new API versions and still support older versions. - -We strongly encourage using compatible API extensions and discourage versioning. -The guidelines for API providers ([SHOULD prefer compatible extensions](@guidelines/R000028)) and consumers ([MUST prepare consumers to accept compatible API extensions](@guidelines/R000029)) enable us (having Postel’s Law in mind) to make compatible changes without versioning. - -There is a difference between incompatible and breaking changes. Breaking changes break existing clients, when deployed into operation. -However, in specific controlled situations, it is possible to deploy incompatible changes in a non-breaking way if no consuming client is using or plans to use the affected API aspects (see also [Deprecation](../030_Deprecation/000_index.md)). diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/030_must-prepare-consumers-to-accept-compatible-api-extensions.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/030_must-prepare-consumers-to-accept-compatible-api-extensions.md deleted file mode 100644 index a187cc2..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/030_must-prepare-consumers-to-accept-compatible-api-extensions.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -type: MUST -id: R000029 ---- - -# prepare consumers to accept compatible API extensions - -API consumers should apply the robustness principle: - -- Be conservative with API inputs and avoid exploiting definition deficits. For example, do not pass megabytes of content for an input string that has no defined maximum length. -- Be tolerant of processing and reading data from API output. - -More specifically, API consumers must be prepared for compatible API extensions of API providers: - -- Be tolerant with unknown fields in the payload (see also Martin Fowler’s post about ["TolerantReader"](http://martinfowler.com/bliki/TolerantReader.html)). -- Be prepared that `x-extensible-enum` output types may deliver new values; either be agnostic or provide default behavior for unknown values (see [SHOULD use extensible enums](@guidelines/R000035)). diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/040_should-use-extensible-enums.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/040_should-use-extensible-enums.md deleted file mode 100644 index 9915792..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/040_should-use-extensible-enums.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -type: SHOULD -id: R000035 ---- - -# use extensible enums - -Enums (represented by `enum` keyword) are not extensible in JSON schema. Adding a new enum value is considered as a breaking change if used in responses. - -Clients need to be prepared that new enum values may be added to an enum without creating a new version. The extension property `x-extensible-enum` has been introduced to clearly signal this intention. The `x-extensible-enum` property contains an open list of values. Each value may have the following properties: - -| Property | Required | Default value | Description | -| ----------- | -------- | ------------- | -------------------------------------------------------------------- | -| value | yes | n/a | The extensible enum value. Must adhere to the specified type. | -| description | yes | n/a | Describes the semantic meaning of the value. | -| deprecated | no | false | A boolean value specifying the deprecation state of this enum value. | -| preview | no | false | A boolean value specifying the preview state of this enum value. | - -`x-extensible-enum` should be used instead of `enum` unless the following applies: - -- The service providing the API owns the enum values. It is part of its domain knowledge. -- The enum represents a closed set in the business domain that will never be extended, even in the future. - -Example usage: - -```yaml -PaymentType: - type: string - description: Describes the payment further. - x-extensible-enum: - - value: CREDIT_CARD - description: Credit card payment - - value: INVOICE - description: Payment by the customer by bank transfer. - deprecated: true - - value: DIRECT_DEBIT - description: Direct debit from a bank account. - preview: true -``` - -Do not use the `enum` keyword in combination with `x-extensible-enum`. - -Note that the "x-extensible-enum" extension property is ignored by most tools. When API clients need to process the different values, the logic must be added manually. This results in extra work for the consumers, but guarantees that automatically generated clients do not break when adding new values. - -References: -- [SHOULD prefer compatible extensions](@guidelines/R000028) -- [`enum` in JSON Schema](http://json-schema.org/understanding-json-schema/reference/generic.html#enumerated-values) -- [Zalando's rule for `x-extensible-enum`](https://opensource.zalando.com/restful-api-guidelines/#112) diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/020_Preview/000_index.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/020_Preview/000_index.md deleted file mode 100644 index 2629f60..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/020_Preview/000_index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Preview of API changes - -One of the main consequences of [contract first](../../../010_CORE-PRINCIPLES/040_Contract-first.md) is that agreed API specifications are published that are not yet or not fully implemented. To make this transparent for all API consumers, there must be the possibility to mark corresponding parts in the API specification as such. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/020_Preview/010_must-not-rely-on-preview.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/020_Preview/010_must-not-rely-on-preview.md deleted file mode 100644 index a47fb2f..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/020_Preview/010_must-not-rely-on-preview.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -type: MUST NOT -id: R000077 -appliesTo: client ---- - -# rely on API components marked as preview - -API specification components marked as preview are intended to inform API consumers about upcoming changes or additions. Details of both the specification and implementation are subject to change and, in case of doubt, will not be used productively, so a productive application should not rely on their availability and reliability. If an API consumer relies on appropriately marked API components, they must check with the API provider to find out when these changes will take effect, and only then can they go live with their own updated API client. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/000_index.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/000_index.md deleted file mode 100644 index 4334178..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/000_index.md +++ /dev/null @@ -1,7 +0,0 @@ -# Deprecation of obsolete API versions and components - -Sometimes it is necessary to phase out an API, an API version or an API feature. -For example, a property is no longer supported, or a whole business functionality is supposed to be removed. -As long as consumers still use API features, removal of these is a breaking change and not allowed. -The following deprecation rules have to be applied to ensure that the necessary consumer changes and actions are well communicated and aligned using _deprecation_ and _sunset_ schedules. -The deprecation phase precedes the final sunset date. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/010_must-obtain-approval-of-consumers-before-api-shutdown.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/010_must-obtain-approval-of-consumers-before-api-shutdown.md deleted file mode 100644 index d3d4dfb..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/010_must-obtain-approval-of-consumers-before-api-shutdown.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -type: MUST -id: R000054 ---- - -# obtain approval of consumers before API shutdown - -Before shutting down an API, an API version or feature, the API provider must ensure that all consumers have given their consent on a sunset date. -The API provider should help consumers to migrate to a potential new API or API feature by providing a migration manual and clearly stating the timeline for replacement availability and sunset (see also [SHOULD add `Deprecation` and `Sunset` header to responses](@guidelines/R000069)). -Once all API consumers have migrated their affected clients, the API provider may shut down the deprecated API feature. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/020_must-collect-external-partner-consent-on-deprecation-time-span.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/020_must-collect-external-partner-consent-on-deprecation-time-span.md deleted file mode 100644 index a2c3d1e..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/020_must-collect-external-partner-consent-on-deprecation-time-span.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -type: MUST -id: R000066 ---- - -# collect external partner consent on deprecation time span - -If the API is actively consumed, the API provider must define a reasonable time span that the API will be maintained after having announced deprecation. -All consumers must state consent with this after-deprecation-life-span, that means the minimum time span between official deprecation and first possible sunset, **before** they are allowed to use the API. diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/030_must-reflect-deprecation-in-api-specifications.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/030_must-reflect-deprecation-in-api-specifications.md deleted file mode 100644 index e3b45d5..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/030_must-reflect-deprecation-in-api-specifications.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -type: MUST -id: R000067 ---- - -# reflect deprecation in specifications - -The deprecation of API elements must be part of the specification (e.g. OpenAPI or AsyncAPI). Each specification format allows for different elements to be deprecated. - -The API provider must set `deprecated: true` for the affected element and add further explanation to the `description` section of the API specification. - -If an API version or feature is deprecated, the API provider must: - -- specify a sunset date in the description -- document in detail what consumers should use instead -- document how to migrate. - -References: -- [OpenAPI deprecated attribute for Schema Object](https://swagger.io/specification/#schema-object) -- [AsyncAPI deprecated attribute for Schema Object](https://www.asyncapi.com/docs/specifications/v2.3.0#schemaObject) diff --git a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/040_must-not-start-using-deprecated-apis.md b/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/040_must-not-start-using-deprecated-apis.md deleted file mode 100644 index 62d1009..0000000 --- a/03_api_guidelines/020_GENERAL-GUIDELINES/030_Compatibility/030_Deprecation/040_must-not-start-using-deprecated-apis.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -type: MUST NOT -id: R000071 -appliesTo: client ---- - -# not start using deprecated APIs - -Consumers must not start using deprecated APIs, API versions or API features. diff --git a/03_api_guidelines/030_REST-GUIDELINES/001_Contract/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/001_Contract/000_index.md deleted file mode 100644 index a278f27..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/001_Contract/000_index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Contract - -This section describes the rules specific to the contract of REST APIs. Also consider the rules defined in [Basics](../../020_GENERAL-GUIDELINES/010_Basics/000_index.md). diff --git a/03_api_guidelines/030_REST-GUIDELINES/001_Contract/010_OpenAPI-specification/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/001_Contract/010_OpenAPI-specification/000_index.md deleted file mode 100644 index e69de29..0000000 diff --git a/03_api_guidelines/030_REST-GUIDELINES/001_Contract/010_OpenAPI-specification/010_must-provide-api-specification-using-openapi-for-rest-apis.md b/03_api_guidelines/030_REST-GUIDELINES/001_Contract/010_OpenAPI-specification/010_must-provide-api-specification-using-openapi-for-rest-apis.md deleted file mode 100644 index 4d4f8b2..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/001_Contract/010_OpenAPI-specification/010_must-provide-api-specification-using-openapi-for-rest-apis.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -type: MUST -id: R000003 ---- - -# provide API specification using OpenAPI for REST APIs - -We use the OpenAPI specification as a standard to define API specification files. -Every API must be described using the OpenAPI specification. - -The API description format used must be [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification). -We will extend it according to our needs by using vendor tags in order to describe the functionality that we require. diff --git a/03_api_guidelines/030_REST-GUIDELINES/001_Contract/010_OpenAPI-specification/030_must-use-semantic-versioning-in-openapi-specification-files.md b/03_api_guidelines/030_REST-GUIDELINES/001_Contract/010_OpenAPI-specification/030_must-use-semantic-versioning-in-openapi-specification-files.md deleted file mode 100644 index 28a7227..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/001_Contract/010_OpenAPI-specification/030_must-use-semantic-versioning-in-openapi-specification-files.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -type: MUST -id: R000064 ---- - -# use semantic versioning in OpenAPI specification files - -In order to generate meaningful changelogs and version numbers, OpenAPI specification files need to follow [semantic versioning](https://semver.org). - -```yaml -openapi: 3.0.3 - -# [...] -info: - title: My Product API - description: Provides basic product information. - contact: - name: FT X - email: FTX-DEV@otto.de - version: 1.0.0 -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/000_index.md deleted file mode 100644 index 17257a2..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# Authorization diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/000_index.md deleted file mode 100644 index 650d648..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/000_index.md +++ /dev/null @@ -1,108 +0,0 @@ -# OAuth 2.0 - -The API uses [OAuth 2.0](https://oauth.net/2/) for authorization. -For the implementation we try to comply with the standards as much as possible. -Here's some general information. - -## Discovery - -The OTTO API provides an [endpoint](https://api.otto.de/.well-known/openid-configuration) that can be used for [OAuth 2.0 endpoint discovery](https://tools.ietf.org/html/draft-ietf-oauth-discovery-06). -Clients can use the returned information to obtain details about the OAuth 2.0 authorization server such as the token and userinfo endpoints as well as the supported OAuth 2.0 flows. - -## Client Management - -OAuth clients and scopes are managed through [Herakles](https://olymp.live.shozu.cloud.otto.de/#/herakles/) (internal link). - - -## JSON Web Token - -As [proposed by the OAuth working group](https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-07) the access tokens used for the OTTO API are JSON Web Tokens (JWT) as defined in [RFC 7797](https://tools.ietf.org/html/rfc7797). - -In short: JWTs are [URL safe base64](https://tools.ietf.org/html/rfc4648#section-5) encrypted JSON documents that encode a - -- cryptographic algorithm & token type -- payload (containing, among other things, the expiration date and scope(s) of the token) and -- signature to allow decentralized verification of said payload - -`Note`{ label } You can find examples, a validator and a collection of libraries for different languages as well as runtime environments at [jwt.io](https://jwt.io/). - -### Example Token - -The JSON content parts of the decoded token look like this: - -**Header** - -```json -{ - "alg": "RS256", // algorithm used for signature - "kid": "public:0235e46d-c7d0-42a4-8f69-c1cb127608e8", // the signing key id - "typ": "JWT" -} -``` - -**Payload** - -```json -{ - "aud": ["https://api.otto.de"], - "client_id": "f3b9910a-08ea-4b6b-895a-261674e573b9", // OAuth client ID that requested the token - "exp": 1591892081, // epoch time at which the token expires - "ext": {}, - "iat": 1591888481, // epoch time the token was issued at - "iss": "https://api.otto.de/", // issuer of the token - "jti": "6f76d949-fad5-4634-ba4f-b7ebf9d32ade", // (unique) ID of the token itself - "nbf": 1591888481, // epoch time the token must not be accepted before - "scp": ["otto.read"], // the scope the token is granting access to - "sub": "8d0c8242d4654d41858e150f5ef5b3deccd749d3" // (if applicable) the subject of the token, in this case a customer -} -``` - -## Large Bearer Tokens -Requesting a large number of scopes will result in large Bearer Tokens. Servers might reject requests containing an `Authorization` header that is larger than 4kB with `413 Payload Too Large` status code. - -## JSON Web Key Set - -With [JSON Web Key Set (JWKS)](https://tools.ietf.org/html/rfc7517), an API can specify the keys it uses to sign its JSON Web Tokens. -For all keys in use it specifies, among other things: - -- the key type (e.g. RSA, EC) -- the intended use of the key (e.g. encryption or signing) -- the key ID -- the specific cryptographic algorithm used -- the key itself - -For a full list of parameters see [RFC7517, Section 4](https://tools.ietf.org/html/rfc7517#section-4). - -An API publishes the keys it uses at `.well-known/jwks.json`. -This allows both clients and endpoints to easily validate the keys used to sign tokens. -Even the API provider can use it to easily rotate keys without manual overhead for API clients or endpoint providers. - -You can find the key set for the OTTO API at [https://api.otto.de/.well-known/jwks.json](https://api.otto.de/.well-known/jwks.json). - -## Refresh Tokens - -Once an access token expires or is about to expire, clients might still need access to OAuth 2.0 protected resources. -Usually this means that the user will be forced to grant permission by re-authenticating. - -To solve this, OAuth 2.0 introduced [refresh tokens](https://tools.ietf.org/html/rfc6749#section-1.5) as part of the access token response. -A refresh token allows an application to obtain a new access token in the background without prompting the user for login credentials and thus not interrupting the user journey. -Typical clients that need a refresh token are mobile and web applications that want to keep the user authenticated for longer than the lifetime of the default access token without having to regularly re-authenticate the user. - -`Note`{ label } A refresh token can only be used once and must be replaced after usage. - -In order to refresh an access token, a client needs to extract the `refresh_token` attribute that comes as part of the JSON response when requesting an access token, and store it for later usage. -When the access token is about to expire the client will use the grant type `refresh_token` (instead of `authorization_code` or `client_credentials`) to fetch a new token. - -Example: - -```http request -POST /oauth2/token HTTP/1.1 -Host: api.otto.de - -grant_type=refresh_token -&refresh_token=xxxxxxxxxxx -&client_id=xxxxxxxxxx -&client_secret=xxxxxxxxxx -``` - -The response to the refresh token grant is the same as when issuing an access token. You can optionally issue a new refresh token in the response, or if you don’t include a new refresh token, the client assumes the current refresh token will continue to be valid. diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/010_must-secure-endpoints-with-oauth2.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/010_must-secure-endpoints-with-oauth2.md deleted file mode 100644 index 1f4e1cb..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/010_must-secure-endpoints-with-oauth2.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -type: MUST -id: R000051 ---- - -# secure endpoints with OAuth 2.0 - -Every API endpoint needs to be secured using OAuth 2.0. diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/020_must-use-authorization-grant.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/020_must-use-authorization-grant.md deleted file mode 100644 index 676eadd..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/020_must-use-authorization-grant.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -type: MUST -id: R000052 -reviewType: automatic ---- - - - -# use Authorization Grant - -Authorization Grant is a credential representing the resource owner's authorization (to access its protected resources) used by the client to obtain an access token. - -The OTTO API supports two grant types: - -- [Authorization Code](https://oauth.net/2/grant-types/authorization-code/) -- [Client Credentials](https://oauth.net/2/grant-types/client-credentials/) - -`Note`{ label } The [Resource Owner Password Credentials](https://oauth.net/2/grant-types/password/) grant type is not supported. - -The grant type to be used depends on the use cases outlined in the following rules. diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/030-should-use-authorization-code-grant-for-confidential-clients.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/030-should-use-authorization-code-grant-for-confidential-clients.md deleted file mode 100644 index e3330ed..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/030-should-use-authorization-code-grant-for-confidential-clients.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -type: SHOULD -id: R000056 ---- - -# use Authorization Code Grant for confidential clients - -The [Authorization Code](https://oauth.net/2/grant-types/authorization-code) grant type should be used by confidential clients to exchange an authorization code for access token and optional refresh token. diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/040-should-use-client-credentials-grant-for-machine-to-machine-authorization.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/040-should-use-client-credentials-grant-for-machine-to-machine-authorization.md deleted file mode 100644 index 14591a9..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/040-should-use-client-credentials-grant-for-machine-to-machine-authorization.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -type: SHOULD -id: R000057 ---- - -# use Client Credentials Grant for machine to machine authorization - -The [Client Credentials](https://oauth.net/2/grant-types/client-credentials) grant should be used for machine-to-machine authorization to obtain an access token **outside of the context of a user**. diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/050_must-use-pkce-for-mobile-and-javascript-apps.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/050_must-use-pkce-for-mobile-and-javascript-apps.md deleted file mode 100644 index d490b5b..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/050_must-use-pkce-for-mobile-and-javascript-apps.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -type: MUST -id: R000053 -appliesTo: client ---- - -# use Proof Key for Code Exchange (PKCE) for mobile and JavaScript apps - -[PKCE](https://oauth.net/2/pkce) ([RFC 7636](https://tools.ietf.org/html/rfc7636)) is an extension to the Authorization Code flow to prevent certain attacks and to be able to securely perform the OAuth 2.0 exchange especially for public clients. -Clients must use SHA256 to encrypt the code challenge and set the `code_challenge_method` parameter to `S256`. - -Tip: -PKCE can be applied to any OAuth 2.0 client and is not restricted to public clients. - diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/060_must-not-use-implicit-grant-flow.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/060_must-not-use-implicit-grant-flow.md deleted file mode 100644 index 1347f43..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/060_must-not-use-implicit-grant-flow.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -type: MUST NOT -id: R000055 -appliesTo: client ---- - -# use Implicit Grant flow - -The [Implicit Grant](https://oauth.net/2/grant-types/implicit) flow was a simplified OAuth flow previously recommended for native apps and JavaScript apps where the access token was returned immediately without an extra authorization code exchange step. - -It is not recommended to use the implicit flow (and some servers prohibit this flow entirely) due to the inherent risks of access tokens being returned in an HTTP redirect without confirmation that they were received by the client. diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/070_must-use-bearer-authentication.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/070_must-use-bearer-authentication.md deleted file mode 100644 index dd9d3a7..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/010_OAuth-2.0/070_must-use-bearer-authentication.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -type: MUST -id: R000021 -appliesTo: client ---- - -# use Bearer Authentication - -Clients resending HTTP requests to the OTTO API must use the `Authorization` header to submit their JWT token to the server using the [Bearer Token](https://tools.ietf.org/html/rfc6750#section-2.1) scheme. - -Example: - -```plaintext -GET /api/orders HTTP/1.1 - -Host: api.otto.de -Authorization: Bearer {JWT Token} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/000_index.md deleted file mode 100644 index 25cd451..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# Scopes diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/010_must-define-and-assign-permissions-by-using-scopes.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/010_must-define-and-assign-permissions-by-using-scopes.md deleted file mode 100644 index 4f3a6c5..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/010_must-define-and-assign-permissions-by-using-scopes.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -type: MUST -id: R000047 ---- - -# define and assign permissions by using scopes - -Endpoints must define permissions to protect access to their resources. -Each endpoint must define at least one OAuth 2.0 scope using the defined [naming conventions](R000048). - -## Granting permission to public resources - -Resources can be classified as _public_. -This is in the responsibility of the resource owner. -The OTTO website can serve as a reference for public resources. -Data that can be accessed there without further login can be defined as public. - -For example: - -- Product data -- Deal of the day - -However, even endpoints providing public resources [must be secured with OAuth 2.0](R000051). -To harmonize the access to public resources we defined the special scope `otto.read`, which can be used to secure those resources. - -Every resource that **cannot be clearly** classified as public has to be considered as private and is not allowed to use the `otto.read` scope. diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/020_shoud-adhere-to-scope-naming-conventions.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/020_shoud-adhere-to-scope-naming-conventions.md deleted file mode 100644 index 283e94b..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/020_Scopes/020_shoud-adhere-to-scope-naming-conventions.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -type: SHOULD -id: R000048 -reviewType: automatic ---- - -# adhere to scope naming conventions - -OAuth 2.0 scopes represent permissions for different resources. -Scopes might consist of two parts: - -- **Required**: `resource`. The resource for the permission, for example `brands`. -- **Optional**: `permission`. The action that can be performed on those resources, for example `read` or `write`. - -To keep a consistent naming pattern, scopes should be constructed according to the following scheme. - -```text -{resource}.{permission} -``` - -`Note`{ label } A scope without explicit permissions grants access to the whole resource. - -## Rules - -The following additional rules apply for scope names: - -- Must only include alphanumeric characters, lowercase letters or the special characters `_` or `-`. -- Must be delimited with dots. -- Must be attributable to a resource. -- Must not include internal product team names as `resource`. -- `resource` should be pluralized when referring to collections and singular for singleton resources. - -## Examples - -DO - -```plaintext -products -products.read -products.write -orders -orders.read -orders.cancel -``` - -DON'T - -```text -Products -opal.products -opal.products.read -product.availability -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/000_index.md deleted file mode 100644 index 80a877f..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# Tokens diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/010_must-validate-json-web-token.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/010_must-validate-json-web-token.md deleted file mode 100644 index 931bfee..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/010_must-validate-json-web-token.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -type: MUST -id: R000050 ---- - -# validate JSON Web Token - -Each endpoint must validate the JWT that the API client has passed along as the access token for its request. - -This includes: - -- the cryptographic signature of the token -- the expiration date of the token -- the scopes encoded in the token (if they match the endpoint) -- that the subject (`sub`-claim) has sufficient rights to access a user-specific resource. This is especially important for tokens that have been granted using the OAuth 2.0 authorization code flow. - -If either of these are not valid the request is to be denied with an appropriate [status code](../../010_HTTP/030_Status-codes/000_index.md) and [error message](../../040_Errors/010_Error-handling/000_index.md). diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/020_must-not-validate-audience-of-the-json-web-token.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/020_must-not-validate-audience-of-the-json-web-token.md deleted file mode 100644 index 78b841e..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/020_must-not-validate-audience-of-the-json-web-token.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -type: MUST NOT -id: R000075 ---- - -# validate audience of the JSON Web Token - -The JWT generated by the OAuth 2.0 Server contains an `aud` field. -The endpoint has to ignore the field and the possible values of this field. - -`Note`{ label } Reserved for future use. diff --git a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/030_must_validate_JWT_based_on_keys in_JWKS_at_all_endpoints.md b/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/030_must_validate_JWT_based_on_keys in_JWKS_at_all_endpoints.md deleted file mode 100644 index 353f2b2..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/005_Authorization/030_Tokens/030_must_validate_JWT_based_on_keys in_JWKS_at_all_endpoints.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -type: MUST -id: R000058 ---- - -# validate JWT based on keys in JWKS at all endpoints - -Each endpoint must validate the JWT used by clients for their requests based on the keys provided by the APIs JWKS mechanism. -This ensures the keys can be rotated easily and minimizes manual efforts for key exchange. - -`Note`{ label } Many libraries already support fetching keys from the API host transparently, if configured to do so. diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/000_index.md deleted file mode 100644 index 03fe6a2..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# HTTP diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/000_index.md deleted file mode 100644 index 8f83418..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# Methods diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/010_must-use-http-methods-correctly.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/010_must-use-http-methods-correctly.md deleted file mode 100644 index a0ec716..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/010_must-use-http-methods-correctly.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -type: MUST -id: R000007 ---- - -# use HTTP methods correctly - -We are compliant with the standardized HTTP method semantics described as follows: - -`GET` requests are used to **read** either a single or a collection resource. - -- For individual resources, `GET` requests will usually generate a `404 Not Found` if the resource does not exist. -- For collection resources, `GET` requests may return either `200 OK` (if the collection is empty) or `404 Not Found` (if the collection is missing). -- `GET` requests must NOT have a request body payload (see `GET With Body`). - -`Note`{ label } `GET` requests on collection resources should provide sufficient [filter](@guidelines/R000049) and [pagination](@guidelines/R000049) mechanisms. - - -## GET with body -APIs sometimes need to provide extensive structured request information with `GET`, that may conflict with the size limits of clients, load balancers, and servers. -As our APIs must be standard compliant (body in `GET` must be ignored on server side), API designers have to check the following two options: - -1. `GET` with URL encoded query parameters: if it is possible to encode the request information in query parameters, respecting the usual size limits of clients, gateways, and servers, this should be the first choice. - The request information can either be provided via multiple query parameters or by a single structured URL encoded string. -2. `POST` with body content: if a `GET` with URL encoded query parameters is not possible, a `POST` with body content must be used. - In this case the endpoint must be documented with the hint `GET with body` to transport the `GET` semantic of this call. - - -Encoding the lengthy structured request information using header parameters is not an option. -From a conceptual point of view, the semantic of an operation should always be expressed by the resource names, as well as the involved path and query parameters, that means, by everything that goes into the URL. -Request headers are reserved for general context information. -In addition, size limits on query parameters and headers are not reliable and depend on clients, gateways, server, and actual settings. -Thus, switching to headers does not solve the original problem. - -## PUT -`PUT` requests are used to **update** (in rare cases to create) **entire** resources – single or collection resources. -The semantic is best described as _"please put the enclosed representation at the resource mentioned by the URL, replacing any existing resource."_. - -- `PUT` requests are usually applied to single resources, and not to collection resources, as this would imply replacing the entire collection. -- `PUT` requests are usually robust against non-existence of resources by implicitly creating before updating. -- On successful `PUT` requests, the server will **replace the entire resource** addressed by the URL with the representation passed in the payload (subsequent reads will deliver the same payload). -- Successful `PUT` requests will usually generate `200 OK` or `204 No Content` (if the resource was updated – with or without actual content returned), and `201 Created` (if the resource was created). - -`Important:`{ label="warning" } It is best practice to prefer `POST` over `PUT` for creation of (at least top level) resources. -This leaves the resource ID under control of the service and allows to concentrate on the update semantic using `PUT` as follows. - -In the rare cases where `PUT` is also used for resource creation, the resource IDs are maintained by the client and passed as a URL path segment. -Putting the same resource twice is required to be idempotent and to result in the same single resource instance (see [MUST fulfill common method properties](@guidelines/R000008)). - -To prevent unnoticed concurrent updates and duplicate creations when using `PUT`, you [SHOULD consider to support `ETag` together with `If-Match`/`If-None-Match` header](@guidelines/R000060) to allow the server to react on stricter demands that expose conflicts and prevent lost updates. - -## POST -`POST` requests are idiomatically used to **create** single resources on a collection resource endpoint, but other semantics on single resources endpoint are equally possible. -The semantic for collection endpoints is best described as _"please add the enclosed representation to the collection resource identified by the URL"_. - -- On a successful `POST` request, the server will create one or multiple new resources and provide their URI/URLs in the response. -- Successful `POST` requests will usually generate `200 OK` (if resources have been updated), `201 Created` with [`Location`](https://tools.ietf.org/html/rfc7231#section-7.1.2) header (if resources have been created), `202 Accepted` (if the request was accepted but has not been finished yet), and exceptionally `204 No Content` with [`Location`](https://tools.ietf.org/html/rfc7231#section-7.1.2) header (if the actual resource is not returned). - -`POST` should be used for scenarios that cannot be covered by the other methods sufficiently. -In such cases, make sure to document the fact that `POST` is used as a workaround (see `GET With Body`). - -Resource IDs related to `POST` requests are created and managed by the server and returned with the response payload and/or as part of the URL in the [`Location`](https://tools.ietf.org/html/rfc7231#section-7.1.2) header. - -Posting the same resource twice is **not** required to be idempotent (check [MUST fulfill common method properties](@guidelines/R000008)) and may result in multiple resources. -However, you [SHOULD consider to design `POST` and `PATCH` idempotent](@guidelines/R000009) to prevent this. - -## PATCH - -`PATCH` requests are used to **update parts** of single resources, i.e. where only a specific subset of resource fields should be replaced. -The semantic is best described as _"please change the resource identified by the URL according to my change request"_. -The semantic of the change request is not defined in the HTTP standard and must be described in the API specification by using suitable media types. - -- `PATCH` requests are usually applied to single resources as patching an entire collection is challenging. -- `PATCH` requests are usually not robust against non-existence of resource instances. -- On successful `PATCH` requests, the server will update parts of the resource addressed by the URL as defined by the change request in the payload. -- Successful `PATCH` requests will usually generate `200 OK` or `204 No Content` (if resources have been updated with or without updated content returned). - -As implementing `PATCH` correctly is a bit tricky, we strongly suggest to choose one and only one of the following patterns per endpoint, unless forced by a backwards compatible change. In preferred order: - -1. Use [`PUT`](#put) with complete objects to update a resource as long as feasible (i.e. do not use `PATCH` at all). -2. Use [`PATCH`](#patch) with partial objects to only update parts of a resource, whenever possible. (This is basically [JSON Merge Patch](https://tools.ietf.org/html/rfc7396), a specialized media type `application/merge-patch+json` (sent as `Content-Type` request header) that is a partial resource representation.) -3. Use [`PATCH`](#patch) with [JSON Patch](https://tools.ietf.org/html/rfc6902), a specialized media type `application/json-patch+json` (sent as `Content-Type` request header) that includes instructions on how to change the resource. -4. Use [`POST`](#post) (with a proper description of what is happening) instead of [`PATCH`](#patch), if the request does not modify the resource in a way defined by the semantics of the media type. - -In practice [JSON Merge Patch](https://tools.ietf.org/html/rfc7396) quickly turns out to be too limited, especially when trying to update single objects in large collections (as part of the resource). -In this cases [JSON Patch](https://tools.ietf.org/html/rfc6902) can show its full power while still showing readable patch requests (see also [JSON patch vs. merge](http://erosb.github.io/post/json-patch-vs-merge-patch)). - -Patching the same resource twice is **not** required to be idempotent (check [MUST fulfill common method properties](@guidelines/R000008)) and may result in a changing result. However, you [SHOULD consider to design `POST` and `PATCH` idempotent](@guidelines/R000009) to prevent this. - -`Note:`{ label } To prevent unnoticed concurrent updates when using `PATCH` you [SHOULD consider to support `ETag` together with `If-Match`/`If-None-Match` header](@guidelines/R000060) to allow the server to react on stricter demands that expose conflicts and prevent lost updates. -Refer to [SHOULD consider to design `POST` and `PATCH` idempotent](@guidelines/R000009) for details and options. - -## DELETE -`DELETE` requests are used to **delete** resources. -The semantic is best described as _"please delete the resource identified by the URL"_. - -- `DELETE` requests are usually applied to single resources, not on collection resources, as this would imply deleting the entire collection. -- Successful `DELETE` requests will usually generate `200 OK` (if some representation of the deleted resource is returned) or `204 No Content` (if no content is returned). - - Depending on the `Access` header of the `DELETE` request, not only a representation of the deleted resource could be returned. Think of returning the whole shopping cart after `DELETE`ing only one lineitem. -- Failed `DELETE` requests will usually generate `404 Not Found` (if the resource cannot be found) or `410 Gone` (if the resource was already deleted before). - -After deleting a resource with `DELETE`, a `GET` request on the resource is expected to either return `404 Not Found` or `410 Gone` depending on how the resource is represented after deletion. -The resource must not be accessible on its endpoint after this operation. - -## HEAD -`HEAD` requests are used to **retrieve** the header information of single resources and resource collections. - -- `HEAD` has exactly the same semantics as `GET`, but returns headers only, no body. - -`Note:`{ label } `HEAD` is particular useful to efficiently lookup whether large resources or collection resources have been updated in conjunction with the [`ETag`](https://tools.ietf.org/html/rfc7232#section-2.3) header. - -## OPTIONS -`OPTIONS` requests are used to **inspect** the available operations (HTTP methods) of a given endpoint. - -- `OPTIONS` responses usually either return a comma separated list of methods in the `Allow` header or a structured list of link templates. - -`Note:`{ label } `OPTIONS` is rarely implemented, though it could be used to self-describe the full functionality of a resource. diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/020_must-fulfill-common-method-properties.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/020_must-fulfill-common-method-properties.md deleted file mode 100644 index 283ac54..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/020_must-fulfill-common-method-properties.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -type: MUST -id: R000008 ---- - -# fulfill common method properties - -Request methods in RESTful services can be: - -- [safe](https://tools.ietf.org/html/rfc7231#section-4.2.1) - the operation semantic is defined to be read-only, meaning it must not have _intended side effects_, i.e. changes, to the server state. -- [idempotent](https://tools.ietf.org/html/rfc7231#section-4.2.2) - the operation has the same _intended effect_ on the server state, independently whether it is executed once or multiple times. - `Note:`{ label } This does not require that the operation is returning the same response or status code. Especially executing a `DELETE` twice might yield a `200 OK` followed by a `404 Not Found` or even `410 Gone`. -- [cacheable](https://tools.ietf.org/html/rfc7231#section-4.2.3) - to indicate that responses are allowed to be stored for future reuse. - In general, requests to safe methods are cacheable, if no current or authoritative response from the server is required. - -Requests can result in numerous server actions such as logging, accounting, collecting metrics, pre-fetching, etc. Clients, however, cannot expect or be held accountable for these _side effects_. -Some server actions, such as rate limiting, may also cause a server-side state change and produce a different response code as a result. This behavior would still allow the methods to be considered safe or idempotent. - -Method implementations must fulfill the following basic properties according to [RFC 7231](https://tools.ietf.org/html/rfc7231): - -| Method | Safe | Idempotent | Cacheable | -| --------- | ---- | ---------- | --------- | -| `GET` | ✔ | ✔ | ✔ | -| `HEAD` | ✔ | ✔ | ✔ | -| `POST` | ✗ | ✗ [^1] | ✗ [^2] | -| `PUT` | ✗ | ✔ | ✗ | -| `PATCH` | ✗ | ✗ [^3] | ✗ | -| `DELETE` | ✗ | ✔ | ✗ | -| `OPTIONS` | ✔ | ✔ | ✗ | - -[^1]: No, but you [SHOULD consider to design `POST` and `PATCH` idempotent](@guidelines/R000009). -[^2]: May, but only if the specific `POST` endpoint is `safe`. `Note:`{ label } Not supported by most caches. -[^3]: No, but you [SHOULD consider to design `POST` and `PATCH` idempotent](@guidelines/R000009). diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/030_should-consider-to-design-post-and-patch-idempotent.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/030_should-consider-to-design-post-and-patch-idempotent.md deleted file mode 100644 index ccc9cd6..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/030_should-consider-to-design-post-and-patch-idempotent.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -type: SHOULD -id: R000009 ---- - -# consider to design `POST` and `PATCH` idempotent - -In many cases it is helpful or even necessary to design `POST` and `PATCH` [idempotent](@guidelines/R000008) for clients to expose conflicts and prevent resource duplication (a.k.a. zombie resources) or lost updates, for example, if the same resources may be created or changed in parallel or multiple times. -To design an idempotent API endpoint owners should consider to apply one of the following two patterns. - -- A resource specific **conditional key** provided via `If-Match` header in the request. The key is generally a meta information of the resource, for example, a _hash_ or _version number_, often stored with it. It allows to detect concurrent creations and updates to ensure idempotent behavior (see [SHOULD consider to support `ETag` together with `If-Match`/`If-None-Match` header](@guidelines/R000060)). -- A resource specific **secondary key** provided as a resource property in the request body. The _secondary key_ is stored permanently in the resource. It allows to ensure idempotent behavior by looking up the unique secondary key in case of multiple independent resource creations from different clients. - -To decide which pattern is suitable for your use case, please consult the following table showing the major properties of each pattern: - -| | Conditional Key | Secondary Key | -| ------------------------------------- | --------------- | ------------- | -| Applicable with | `PATCH` | `POST` | -| HTTP Standard | ✔ | ✗ | -| Prevents duplicate (zombie) resources | ✔ | ✔ | -| Prevents concurrent lost updates | ✔ | ✗ | -| Supports safe retries | ✔ | ✔ | -| Can be inspected (by intermediaries) | ✔ | ✗ | -| Usable without previous `GET` | ✗ | ✔ | - -`Note:`{ label } The patterns applicable to `PATCH` can be applied in the same way to `PUT` and `DELETE` providing the same properties. - -The most important pattern to design `POST` idempotent for creation is to introduce a resource specific **secondary key** provided in the request body, to eliminate the problem of duplicate (a.k.a zombie) resources. -Keep in mind that when creating a new resource using `POST` the resource identifier is created on the server-side, therefore the secondary key has to be provided by the client to resolve possible conflicts. - -The secondary key is stored permanently in the resource as an _alternate key_ or _combined key_ (if consisting of multiple properties) guarded by a uniqueness constraint enforced server-side, that is visible when reading the resource. -The best and often naturally existing candidate is a _unique foreign key_, that points to another resource having _one-to-one_ relationship with the newly created resource, e.g. a parent process identifier. - -An example for a secondary key might be the e-mail address on a user resource: - -```sh -POST /users HTTP/1.1 - -{ - "mail": "api@otto.de", - "name": "Api User" -} - -# The response might never arrive at the client... -201 Created -Location: /users/12345 - -# ...so the client retries the request... -POST /users HTTP/1.1 - -{ - "mail": "api@otto.de", - "name": "Api User" -} - -# ...resulting in a conflict, because the resource has already been created for the given secondary key "mail". - -409 Conflict -``` - -When using the secondary key pattern all subsequent retries should fail with status code `409 Conflict`. -We suggest to avoid `200 OK` here unless you make sure, that the delivered resource is the original one implementing a well defined behavior. Using `204 No Content` without content would be a similar well-defined option. diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/040_may-use-patch-with-json-patch-test-operation-for-concurrency-control.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/040_may-use-patch-with-json-patch-test-operation-for-concurrency-control.md deleted file mode 100644 index a7b8b3d..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/010_Methods/040_may-use-patch-with-json-patch-test-operation-for-concurrency-control.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -type: MAY -id: R000059 ---- - -# use `PATCH` with JSON Patch `test` operation for concurrency control - -In a situation where partial updates on different properties of an entity are common, chances of running into an optimistic locking situation increase with the number of concurrent updates, even if embracing [SHOULD use `ETag` together with `If-Match`/`If-None-Match` header for concurrency control](@guidelines/R000060). Performing a partial update using `PATCH` with media type `application/json-patch+json` (see [RFC 6902](https://tools.ietf.org/html/rfc6902)) can guard against unnoticed concurrent updates of properties relevant for the particular update. - -JSON Patch offers a [`test` operation](https://tools.ietf.org/html/rfc6902#section-4.6) that allows a server to reject a partial update, if the condition defined by the client cannot be met. - -Example: - -```http -PATCH /products/123 HTTP/1.1 -Content-Type: application/json-patch+json -[ - { "op": "test", "path": "description", "value": "An old description" }, - { "op": "replace", "path": "description", "value": "A new description" } -] - -HTTP/1.1 200 OK -ETag: "sadfgerlasdgjrgg" -{ "id": "123", "description": "A new description", ... } -``` - -Or in an optimistic locking situation: - -```http -PATCH /products/123 HTTP/1.1 -Content-Type: application/json-patch+json -[ - { "op": "test", "path": "description", "value": "An old description" }, - { "op": "replace", "path": "description", "value": "A new description" } -] - -HTTP/1.1 409 Conflict -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/000_index.md deleted file mode 100644 index 24e106b..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/000_index.md +++ /dev/null @@ -1,68 +0,0 @@ -# Headers - -## List of headers - -## Headers - -The list of headers is not supposed to be exhaustive, but contains the most common headers used in the context of the API. -We do not prohibit the use of headers that are not listed below. -HTTP/1.1-related headers, for example, `Connection`, are not explicitly listed. - -| Header Name | Description | Part of Request | Part of Response | -| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------: | :--------------: | -| `Accept` | Used for content negotiation, indicates which content types the client understands in a response. Refer to [SHOULD use `Accept` and `Content-Type` headers with profile parameter](@guidelines/R000030). | ✔ | ✗ | -| `Accept-Encoding` | Used for content negotiation, a client advertises which content encoding algorithms it understands in a response. Possible values are `gzip`, `compress`, `deflate`, `identity`, and `br`. | ✔ | ✗ | -| `Allow` | Contains the set of methods supported by a resource. This header must be set when responding with `405 Method Not Allowed`. Example: `Allow: GET, PUT, HEAD`. | ✗ | ✔ | -| `Authorization` | Includes the credentials for accessing a given resource. Refer to [MUST use Bearer Authentication](@guidelines/R000021). | ✔ | ✗ | -| `Content-Encoding` | Indicates the content encoding used for the response body. Refer to `Accept-Encoding`. | ✗ | ✔ | -| `Content-Length` | The size of the request payload or response body in bytes. | ✔ | ✔ | -| `Content-Type` | Indicates the media type of a resource. Describes the payload format of requests and the content type of responses. Required for `PUT` and `POST` requests. Refer to [SHOULD use `Accept` and `Content-Type` headers with profile parameter](@guidelines/R000030) | ✔ | ✔ | -| `Date` | Contains the timestamp of the request (client) and response (server) respectively. The timestamp format must follow [RFC 7231](https://tools.ietf.org/html/rfc7231#section-7.1.1.1) | ✔ | ✔ | -| `ETag` | Used for [caching](@guidelines/R000010) and [concurrency control](@guidelines/R000060). | ✗ | ✔ | -| `Forwarded` | Contains information from the client side of proxy servers that is altered or lost when a proxy is involved. This can be the original `Host` requested by a client, for example to [generate absolute URLs in links](@guidelines/R100032). Refer to [RFC 7239](https://tools.ietf.org/html/rfc7239). | ✔ | ✗ | -| `Host` | Contains the hostname (and non-default port) of the client's request. Example: `Host: api.otto.de` | ✔ | ✗ | -| `If-Match` | Used for [caching](@guidelines/R000010) and [concurrency control](@guidelines/R000060). | ✔ | ✗ | -| `If-None-Match` | Used for [caching](@guidelines/R000010) and [concurrency control](@guidelines/R000060). | ✔ | ✗ | -| `Location` | Contains the redirect URL. This URL must be fully qualified. | ✗ | ✔ | -| `Retry-After` | Used for rate limiting. Refer to [MUST use code 429 with headers for rate limits](@guidelines/R000014). | ✗ | ✔ | -| `Server` | The header describes the software used by the server that handled the request. | ✗ | ✔ | -| `User-Agent` | Used by a client to identify itself to the server. It should include a unique, human-readable identifier, optionally suffixed by a version string reflecting different software releases of the client. Example: [`User-Agent: otto-ready/v2.3.1`](@guidelines/R000025) | ✔ | ✗ | -| `X-RateLimit-Limit` | Used for rate limiting. Refer to [MUST use code 429 with headers for rate limits](@guidelines/R000014). | ✗ | ✔ | -| `X-RateLimit-Remaining` | Used for rate limiting. Refer to [MUST use code 429 with headers for rate limits](@guidelines/R000014). | ✗ | ✔ | -| `X-RateLimit-Reset` | Used for rate limiting. Refer to [MUST use code 429 with headers for rate limits](@guidelines/R000014). | ✗ | ✔ | - -References: -- [MUST NOT use link headers for JSON representations](@guidelines/R100034) - -## Header fields - -## ETag -The RFC 7232 `ETag` header field in a response provides the entity tag of a selected resource. The entity tag is an opaque identifier for versions and representations of the same resource over time, regardless whether multiple versions are valid at the same time. -An entity tag consists of an opaque **quoted** string, possibly prefixed by a weakness indicator (refer to [RFC 7232 Section 2.3](https://tools.ietf.org/html/rfc7232#section-2.3)). -The contents of an `ETag: ` header is either: - -​ a) a hash of the response body, - -​ b) a hash of the last modified field of the entity, or - -​ c) a version number or identifier of the entity version. - -Example: `W/"xy"`, `"5"`, `"5db68c06-1a68-11e9-8341-68f728c1ba70"` - -## If-Match -The RFC 7232 `If-Match` header field in a request requires the server to only operate on the resource that matches at least one of the provided entity-tags. -This allows clients to express a precondition that prevents the method from being applied if there have been any changes to the resource (refer to [RFC 7232 Section 3.1](https://tools.ietf.org/html/rfc7232#section-3.1)). - -Example: `"5"`, `"7da7a728-f910-11e6-942a-68f728c1ba70"` - -## If-None-Match -The RFC 7232 `If-None-Match` header field in a request requires the server to only operate on the resource if it does **not** match any of the provided entity-tags. If the provided entity-tag is `*`, it is required that the resource does not exist at all (refer to [RFC 7232 Section 3.2](https://tools.ietf.org/html/rfc7232#section-3.2)). - -Example: `"7da7a728-f910-11e6-942a-68f728c1ba70"`, `*` - -## Location -The `Location` header includes a fully qualified URL. This URL [must also be absolute](@guidelines/R100032) and respect any `Forwarded` header. -Use this for two use cases: - -- Redirection: When answering a request with a `3xx` status code, the header value should point to where the resource moved. -- Creation: When succesfully creating a resource via `POST`, you should tell a client the final location of that resource using the `Location` header. If a resource was created via `PUT` the client is already aware of the resource location, in this instance you should not set the `Location` header. diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/010_may-use-etag-header-for-caching-resources.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/010_may-use-etag-header-for-caching-resources.md deleted file mode 100644 index f76e366..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/010_may-use-etag-header-for-caching-resources.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -type: MAY -id: R000010 ---- - -# use `ETag` header for caching resources - -Using the `ETag` response header in combination with the `If-None-Match` request header is a powerful tool for caching resources. -This approach offers a solution where other caching headers (e.g. `Cache-Control` or `Expires`) hint at a _stale_ resource on the client side. - -When implementing `ETag` for caching, also "[SHOULD use `ETag` together with `If-Match`/`If-None-Match` header for concurrency control](@guidelines/R000060)" applies, see below "pitfalls". - -```sh -GET /products/abc123 HTTP/1.1 - -# Server sends ETag with requested resource -200 OK -ETag: "5db68c06-1a68-11e9-8341-68f728c1ba70" -{/* big payload */} - -# Client passes ETag in `If-None-Match` header on subsequent requests -GET /products/abc123 HTTP/1.1 -If-None-Match: "5db68c06-1a68-11e9-8341-68f728c1ba70" - -# Server compares ETag values, indicates that the client version is up to date. -# The payload is not transmitted again. -304 Not Modified - -# Down the line the resource has been changed, the client requests it again -GET /products/abc123 HTTP/1.1 -If-None-Match: "5db68c06-1a68-11e9-8341-68f728c1ba70" - -# Server compares Etag values, determines that the clients version is stale. -# The GET request is fully excuted, the payload and updated ETag are transmitted. -200 OK -ETag: "8341-5db68c06-68f728c1ba70-1a68-11e9" -{/* big payload */} -``` - -The semantic is best described as: _"please give me the representation of the current state of the resource, if the state changed compared to the version I already know about."_ - -The purpose of the value is to indicate a change in the underlying resource. -One must differentiate between _weakly_ and _strongly_ validating entity tags: - -- A _strong_ entity tag indicates a byte-by-byte equality if matching and should be the **default**. -- A _weak_ entity tag, marked by a `W/` prefix, only indicates semantic equality of the underlying resource. It should be the **fallback** if generating a strong tag is unfeasible, e.g. due to performance reasons. - -There are [several pitfalls](https://www.mnot.net/blog/2007/08/07/etags) to consider when implementing the `ETag` header correctly: - -- A strong `ETag` value must change when the representation of an entity changes, so it has to be sensitive to `Content-Type`, `Content-Encoding` and other response characteristics in order to be compliant with [RFC 7232](https://tools.ietf.org/html/rfc7232#section-2.3). -- Using `gzip` compression will include a timestamp in your compressed resource representation, resulting in a different `ETag` value when compressed at another time even though the resource has not changed at all. -- Handing out `ETag` headers for caching also implies, that your API also supports concurrency control/optimistic locking via `ETag`. This might add unwanted development and operational overhead. -- You might find yourself doing a bunch of (CPU-bound) work on the server only to validate incoming `If-None-Match` request headers. In this case using `ETag` will only save network bandwidth, while still incurring compute costs, dwarfing the actual returns expected from implementing `ETag`. -- `ETag` for collection resources are nontrivial to implement (see below). - -## Caching collection resources - -Caching via the `ETag` and `If-None-Match` header may also be applicable for collection resources, though the semantics are not as straightforward as for single entities. -While it is easy to determine whether a single underlying entity changed, it is nonobvious when the state of a whole collection changed. -A collection may be viewed as changed when: - -- a single entity of the given collection changed -- or the order of the collection items changed -- or the number of items in the collection changed. - -A _shallow_ comparison might be useful for some clients, while a _deep_ comparison could be necessary for use cases with stronger requirements. -No general rule can be derived, the behavior needs be defined on a case-by-case basis for the given application. diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/020_should-use-etag-together-with-if-match-if-none-match-header-for-concurrrency-control.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/020_should-use-etag-together-with-if-match-if-none-match-header-for-concurrrency-control.md deleted file mode 100644 index 65b434a..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/020_should-use-etag-together-with-if-match-if-none-match-header-for-concurrrency-control.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -type: SHOULD -id: R000060 ---- - -# use `ETag` together with `If-Match`/`If-None-Match` header for concurrency control - -When creating or updating resources it may be necessary to expose conflicts and to prevent the 'lost update' or 'initially created' problem. -Following [RFC 7232 "HTTP: Conditional Requests"](https://tools.ietf.org/html/rfc7232), this can be best accomplished by supporting the [`ETag`](https://tools.ietf.org/html/rfc7232#section-2.3) header together with the [`If-Match`](https://tools.ietf.org/html/rfc7232#section-3.1) or [`If-None-Match`](https://tools.ietf.org/html/rfc7232#section-3.2) conditional header. - -## Updating resources without 'lost update' problem -To expose conflicts between concurrent update operations via `PUT`, `POST`, or `PATCH`, the `If-Match: ` header can be used to enable the server to check whether the version of the updated entity is conforming to the requested [``](https://tools.ietf.org/html/rfc7232#section-2.3). -If no matching entity is found, the operation is supposed to respond with status code `412 - Precondition Failed`. - -Example: - -```http -GET /orders HTTP/1.1 - -HTTP/1.1 200 OK -{ - "items": [ - { "id": "O0000042" }, - { "id": "O0000043" } - ] -} -``` - -```http -GET /orders/O0000042 HTTP/1.1 - -HTTP/1.1 200 OK -ETag: "osjnfkjbnkq3jlnksjnvkjlsbf" -{ "id": "BO0000042", ... } -``` - -```http -PUT /orders/O0000042 HTTP/1.1 -If-Match: "osjnfkjbnkq3jlnksjnvkjlsbf" -{ "id": "O0000042", ... } - -HTTP/1.1 204 No Content -``` - -Or, if there was an update since the `GET` and the entity’s `ETag` has changed: - -```http -PUT /orders/O0000042 HTTP/1.1 -If-Match: "osjnfkjbnkq3jlnksjnvkjlsbf" -{ "id": "O0000042", ... } - -HTTP/1.1 412 Precondition failed -``` - -## Creating resources without 'initially created' problem -Besides other use cases, `If-None-Match: *` can be used in a similar way to expose conflicts in resource creation. -If any matching entity is found, the operation is supposed to respond with status code `412 Precondition Failed`. - -Example: - -```http -GET /orders HTTP/1.1 - -HTTP/1.1 200 OK -{ - "items": [ - { "id": "O0000042" } - ] -} -``` - -```http -PUT /orders/O0000042 HTTP/1.1 -If-None-Match: * -{ "id": "O0000042", ... } - -HTTP/1.1 412 Precondition Failed -``` - -## Enforce conditional requests -In order to enforce the usage of conditional requests, the server is supposed to answer with status code `428 Precondition Required` in case of clients omitting the `If-Match`/`If-None-Match` request header. - -Example: - -```http -PUT /orders/O0000042 HTTP/1.1 -{ "id": "O0000042", ... } - -HTTP/1.1 428 Precondition Required -``` - -Using `HEAD` instead of `GET` in order to just fetch the most current `ETag` value is always an option to save bandwidth! - -References: -- [MAY use `ETag` header for caching resources](@guidelines/R000010) diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/030_should-honor-available-etag-header-on-subsequent-modifications.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/030_should-honor-available-etag-header-on-subsequent-modifications.md deleted file mode 100644 index e586bd3..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/030_should-honor-available-etag-header-on-subsequent-modifications.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -type: SHOULD -id: R000074 ---- - -# honor available `ETag` header on subsequent modifications - -In addition to the normal payload, an optional `ETag` header can be part of the response to a `GET` or `HEAD` request. - -A client should use the `ETag` response header value of a prior request as `If-Match: ` request header on subsequent `PUT`, `PATCH` or `POST` requests for making modifications to a resource. This also applies for services, that introduced the `ETag` header with the sole intention of [improving cachability](@guidelines/R000010). diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/040_should-not-use-last-modified-and-if-unmodified-since-headers-for-concurrency-control.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/040_should-not-use-last-modified-and-if-unmodified-since-headers-for-concurrency-control.md deleted file mode 100644 index 44bcc2b..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/040_should-not-use-last-modified-and-if-unmodified-since-headers-for-concurrency-control.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -type: SHOULD NOT -id: R000072 ---- - -# use `Last-Modified` and `If-Unmodified-Since` headers for concurrency control - -APIs should not use the `Last-Modified` header to achieve concurrency control. -The header only provides a time resolution of one second, which is too coarse for most use cases. -You might be able to use this header in certain less constraint cases. - -If you choose to implement this behavior nevertheless, you should communicate this to clients by responding with `428 Precondition Required` for requests that do not contain the corresponding `If-Unmodified-Since` header. - -References: -- [SHOULD follow concurrenct update pattern with `If-Modified-Since` header](@guidelines/R000073) -- [SHOULD use `ETag` together with `If-Match`/`If-None-Match` header for concurrency control](@guidelines/R000060) diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/050_should-follow-concurrenct-update-pattern-with-if-umodified-since-header.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/050_should-follow-concurrenct-update-pattern-with-if-umodified-since-header.md deleted file mode 100644 index 8b0f885..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/020_Headers/050_should-follow-concurrenct-update-pattern-with-if-umodified-since-header.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -type: SHOULD -id: R000073 -appliesTo: client ---- - -# follow concurrent update pattern with `If-Unmodified-Since` header - -If an API implements concurrency control via the `Last-Modified` header, clients should follow this pattern. -This means, a client should send a received `Last-Modified` timestamp using the `If-Unmodified-Since` header. -This allows the server to verify the conditional request. - -If you do not provide the header, the server may respond with `428 Precondition Required`. - -References: -- [SHOULD NOT use `Last-Modified` and `If-Unmodified-Since` headers for concurrency control](@guidelines/R000072) -- [SHOULD use `ETag` together with `If-Match`/`If-None-Match` header for concurrency control](@guidelines/R000060) diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/000_index.md deleted file mode 100644 index 1ad8b77..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# Status codes diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/010_must-specify-success-and-error-responses.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/010_must-specify-success-and-error-responses.md deleted file mode 100644 index 5ead1b3..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/010_must-specify-success-and-error-responses.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -type: MUST -id: R000011 ---- - -# specify success and error responses - -APIs should define the functional, business view and abstract from implementation aspects. -Success and error responses are a vital part to define how an API is used correctly. - -Therefore, you must define **all** success and service specific error responses in your API specification. -Both are part of the interface definition and provide important information for service clients to handle standard as well as exceptional situations. - -`Note:`{ label } In most cases it is not useful to document all technical errors, especially if they are not under control of the service provider. Thus unless a response code conveys application-specific functional semantics or is used in a non-standard way that requires additional explanation, multiple error response specifications can be combined using the following pattern: - -See [Error Handling](../../040_Errors/010_Error-handling/000_index.md) for more details. - -```yaml -responses: - ... - default: - description: error occurred - see status code and problem object for more information. - content: - "application/problem+json": - schema: - $ref: 'https://api.otto.de/problem/schema.yaml#/Problem' -``` - -API designers should also think about a **troubleshooting board** as part of the associated online API documentation. -It provides information and handling guidance on application-specific errors and is referenced via links from the API specification. -This can reduce service support tasks and contribute to service client and provider performance. diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/020_must-use-standard-http-status-codes.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/020_must-use-standard-http-status-codes.md deleted file mode 100644 index 1bc7c13..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/020_must-use-standard-http-status-codes.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -type: MUST -id: R000012 ---- - -# use standard HTTP status codes - -You must only use standardized HTTP status codes consistently with their intended semantics. -You must not invent new HTTP status codes. - -RFC standards define ~60 different HTTP status codes with specific semantics (mainly [RFC7231](https://tools.ietf.org/html/rfc7231#section-6) and [RFC 6585](https://tools.ietf.org/html/rfc6585)) — and there are upcoming new ones, for example, [draft legally-restricted-status](https://tools.ietf.org/html/draft-tbray-http-legally-restricted-status-05). -Refer to the overview of all error codes at [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) or via also including 'unofficial codes', for example, used by popular web servers like Nginx. - -Below we list the most commonly used and best understood HTTP status codes, consistent with their semantic in the RFCs. -APIs should only use these to prevent misconceptions that arise from less commonly used HTTP status codes. - -As long as your HTTP status code usage is well covered by the semantic defined here, you should not describe it to avoid an overload with common sense information and the risk of inconsistent definitions. Only if the HTTP status code is not in the list below or its usage requires additional information aside the well defined semantic, the API specification must provide a clear description of the HTTP status code in the response. - - -## Success codes - -| Status Code | Meaning | Methods | -| :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------- | -| `200 OK` | This is the standard success response. | | -| `201 Created` | Returned on successful entity creation. You are free to return either an empty response or the created resource in conjunction with the `Location` header (readers can find more details in Common headers. _Always_ set the `Location` header when the client needs to know the URI of the newly created resource. | `POST`, `PUT` | -| `202 Accepted` | The request was successful and will be processed asynchronously. | `POST`, `PUT`, `PATCH`, `DELETE` | -| `204 No Content` | No response body. | `PUT`, `PATCH`, `DELETE` | - - -## Redirection codes - -| Code | Meaning | Methods | -| :----------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------- | -| `301 Moved Permanently` | This request and all future requests should be directed to the given URI. | `` | -| `303 See Other` | The response to the request can be found under another URI using a `GET` method. | `POST`, `PUT`, `PATCH`, `DELETE` | -| `304 Not Modified` | Indicates that a conditional `GET` or `HEAD` request would have resulted in `200` response if it were not for the fact that the condition evaluated to false, i.e. resource has not been modified since the date or version passed via request headers [`If-Modified-Since`](https://tools.ietf.org/html/rfc7232#section-3.3) or [`If-None-Match`](https://tools.ietf.org/html/rfc7232#section-3.2). | `GET`, `HEAD` | -| `307 Temporary Redirect` | The response to the request can be temporarily found under another URI using the same method of the initial request. | `` | -| `308 Permanent Redirect` | The response to the request can be permanently found under another URI using the same method of the initial request. | `` | - - -## Client side error codes - -| Code | Meaning | Methods | -| :--------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------- | -| `400 Bad Request` | Indicates a syntactically malformed request. | `` | -| `401 Unauthorized` | The users must log in (this often means "Unauthenticated"). | `` | -| `403 Forbidden` | The user is not authorized to use this resource. | `` | -| `404 Not Found` | The requested resource could not be found. | `` | -| `405 Method Not Allowed` | The method is not supported, refer to [OPTIONS](@guidelines/R000007). | `` | -| `406 Not Acceptable` | Resource can only generate content not acceptable according to the Accept headers sent in the request. | `` | -| `409 Conflict` | Request cannot be completed due to conflict, e.g. when two clients try to create the same resource or if there are concurrent, conflicting updates. | `POST`,`PUT`,`PATCH`,`DELETE` | -| `410 Gone` | Resource does not exist any longer, e.g. when accessing a resource that has intentionally been deleted. | `` | -| `412 Precondition Failed` | Returned for conditional requests, e.g. [`If-Match`](https://tools.ietf.org/html/rfc7232#section-3.1) if the condition failed. Used for optimistic locking. | `PUT`,`PATCH`,`DELETE` | -| `413 Payload Too Large` | Request headers or body exceed a defined limit. This might happen for large JWT containing many scopes or large HTTP bodies. | `` | -| `415 Unsupported Media Type` | E.g. client sends request body without content type. | `POST`,`PUT`,`PATCH`,`DELETE` | -| `422 Unprocessable Entity` | Indicates a logically invalid request body. The server understands the content type of the request entity and the syntax is correct. However, the server was unable to process the contained instructions, for example, due to an inappropriate server state. | `POST`,`PUT`,`PATCH`,`DELETE` | -| `428 Precondition Required` | Server requires the request to be conditional, e.g. to make sure that the "lost update problem" is avoided (refer to [SHOULD consider to support `ETAG` together with If-Match/If-None-Match header](@guidelines/R000060)). | `` | -| `429 Too Many Requests` | The client does not consider rate limiting and sent too many requests (refer to [MUST use code 429 with headers for rate limits](@guidelines/R000014)). | `` | - - -## Server side error codes - -| Code | Meaning | Methods | -| :-------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------ | -| `500 Internal Server Error` | A generic error indication for an unexpected server execution problem (here, client retry may be sensible) | `` | -| `501 Not Implemented` | Server cannot fulfill the request (usually implies future availability, e.g. new feature). | `` | -| `503 Service Unavailable` | Service is (temporarily) not available (e.g. if a required component or downstream service is not available) — client retry may be sensible. If possible, the service should indicate how long the client should wait by setting the [`Retry-After`](https://tools.ietf.org/html/rfc7231#section-7.1.3) header. | `` | -| | | - diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/030_must-use-most-specific-http-status-code.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/030_must-use-most-specific-http-status-code.md deleted file mode 100644 index 6a87556..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/030_must-use-most-specific-http-status-code.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -type: MUST -id: R000013 ---- - -# use most specific HTTP status code - -You must use the most specific HTTP status code when returning information about your request processing status or error situations. diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/040_must-use-code-429-with-headers-for-rate-limits.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/040_must-use-code-429-with-headers-for-rate-limits.md deleted file mode 100644 index 5bc6b84..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/040_must-use-code-429-with-headers-for-rate-limits.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -type: MUST -id: R000014 -reviewType: automatic ---- - -# use code 429 with headers for rate limits - -APIs that intend to manage the request rate of clients must use the `429 Too Many Requests` response code, if the client exceeded the request rate (refer to [RFC 6585](https://tools.ietf.org/html/rfc6585)). -Such responses must also contain header information providing further details to the client. -There are two approaches a service can take for header information: - -- Return a [`Retry-After`](https://tools.ietf.org/html/rfc7231#section-7.1.3) header indicating how long the client ought to wait before making a follow-up request. The Retry-After header can contain a HTTP date value to retry after or the number of seconds to delay. Either is acceptable but APIs should prefer to use a delay in seconds. -- Return a trio of `X-RateLimit` headers. These headers (described below) allow a server to express a service level in the form of a number of allowing requests within a given window of time and when the window is reset. - -The `X-RateLimit` headers are: - -- `X-RateLimit-Limit`: The maximum number of requests that the client is allowed to make in this window. -- `X-RateLimit-Remaining`: The number of requests allowed in the current window. -- `X-RateLimit-Reset`: The relative time in seconds when the rate limit window will be reset. - `Note`{ label } This is different to GitHub and Twitter’s usage of a header with the same name which is using UTC epoch seconds instead. - -The reason to allow both approaches is that APIs can have different needs. -Retry-After is often sufficient for general load handling and request throttling scenarios and notably, does not strictly require the concept of a calling entity such as a tenant or named account. -In turn this allows resource owners to minimize the amount of state they have to carry with respect to client requests. -The 'X-RateLimit' headers are suitable for scenarios where clients are associated with pre-existing account or tenancy structures. -`X-RateLimit` headers are generally returned on every request and not just on a 429, which implies the service implementing the API is carrying sufficient state to track the number of requests made within a given window for each named entity. diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/050_must-set-user-agent.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/050_must-set-user-agent.md deleted file mode 100644 index 17ee779..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/030_Status-codes/050_must-set-user-agent.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -type: MUST -id: R000025 -appliesTo: client ---- - -# set user agent request header - -Clients must set the `User-Agent` header when performing requests against the OTTO API in the format `{client-identifier}/{client-version}`. This allows requests to be correlated with the specific client and release version, which can be used to troubleshoot failed requests for a new version of the client application. - -Examples: - -- `acme-product-indexer/v1.0.0` -- `otto-alexa-skill/v2.3.0` diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/000_index.md deleted file mode 100644 index 47986cc..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/000_index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Caching - -**Note:** The OTTO API does not provide any caching capabilities by itself. Caching must be implemented by the backends. diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/10_should-adhere-to-caching-best-practices.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/10_should-adhere-to-caching-best-practices.md deleted file mode 100644 index 8aff557..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/10_should-adhere-to-caching-best-practices.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -type: SHOULD -id: R006010 ---- - -# adhere to caching best practices - -For consistent cache handling amongst services, adhere to the best practices shown below: - -- Avoid client side and transparent web caching. - - Read [RFC 7234](https://tools.ietf.org/html/rfc7234) before adding any client or proxy cache. -- Since all endpoints are [authorized via OAuth2](../../005_Authorization/020_Scopes/010_must-define-and-assign-permissions-by-using-scopes.md), the default `Cache-Control` header should be `Cache-Control: private, must-revalidate` with a `max-age` value between some seconds to some hours. -- Use the `Cache-Control` (HTTP 1.1) header instead of the `Pragma` (HTTP 1.0) header. -- Consider using the `ETag` header when caching. - - See: [MAY use `ETag` header for caching resources](@guidelines/R000010) and [SHOULD use `ETag` together with `If-Match`/`If-None-Match` header for concurrency control](@guidelines/R000060) -- Avoid the `Last-Modified` header when possible. - - See: [SHOULD NOT use `Last-Modified` and `If-Unmodified-Since` headers for concurrency control](../010_Methods/040_may-use-patch-with-json-patch-test-operation-for-concurrency-control.md) -- Avoid the `Expires` header to prevent redundant and ambiguous definition of cache lifetime. diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/20_must-document-cacheable-get-head-and-post-endpoints.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/20_must-document-cacheable-get-head-and-post-endpoints.md deleted file mode 100644 index d3b2e03..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/20_must-document-cacheable-get-head-and-post-endpoints.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -type: MUST -id: R006020 ---- - -# document cacheable `GET`, `HEAD` and `POST` endpoints - -To clearly document that a `GET`, `HEAD` or `POST` endpoint implements any kind of caching, the support of caching headers (`Cache-Control`, `Vary`, `Etag`) must be declared in the response. - -## Example OpenAPI Spec documentation fragment - -```yaml -paths: - "/products": - get: - operationId: products-read - summary: This endpoint will return a collection of products. - description: | - Load a collection of products. - responses: - 200: - description: Successfully load products - headers: - Cache-Control: - description: > - Indicates if this response is cacheable. - See [RFC 7234](https://tools.ietf.org/html/rfc7234#section-5.2.2) for possible values. - schema: - type: string - content: - 'application/json+hal;profile="https://api.otto.de/portal/profiles/products/products+v1"': - schema: - "$ref": "#/components/schemas/LoadProductsV1Response" -``` - -See: - -- [MAY use `ETag` header for caching resources](@guidelines/R000010) -- [SHOULD use `ETag` together with `If-Match`/`If-None-Match` header for concurrency control](@guidelines/R000060) diff --git a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/30_should-avoid-vary-header-for-caching.md b/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/30_should-avoid-vary-header-for-caching.md deleted file mode 100644 index 9a540bc..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/010_HTTP/040_Caching/30_should-avoid-vary-header-for-caching.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -type: SHOULD -id: R006030 ---- - -# avoid `Vary` header for caching - -The `Vary` header as specified in [RFC7231#section-7.1.4](https://tools.ietf.org/html/rfc7231#section-7.1.4) is difficult to setup in order to support correct caching. For example, implementing secondary key calculation as described in [RFC7234#section-4.1](https://tools.ietf.org/html/rfc7234#section-4.1) has a high potential for mistakes. Whenever possible, use the `ETag` header instead of `Vary` for caching. - -See: - -- [MAY use `ETag` header for caching resources](@guidelines/R000010) -- [SHOULD use `ETag` together with `If-Match`/`If-None-Match` header for concurrency control](@guidelines/R000060) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/000_index.md deleted file mode 100644 index 3fbe632..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/000_index.md +++ /dev/null @@ -1,9 +0,0 @@ -# Hypermedia - -Besides the best practices for [compatible API evolutions](../../020_GENERAL-GUIDELINES/030_Compatibility/010_Compatible-changes/000_index.md), there are other guidelines to facilitate business changes without impacting consumers. - -To achieve this, API contracts should not contain or publish explicit or implicit business rules, such as the conditions under which a resource is usable. These rules would then be part of the API contract, and any incompatible change to these rules (e.g. a stricter interpretation) would break API clients. - -Instead, API responses should include information about when certain contextually relevant resources are accessible and thus usable. This information is commonly referred to as hypermedia. - -This section deals with topics such as [when hypermedia needs to be implemented](@guidelines/R000033), [which hypermedia standard to use](@guidelines/R000036), details about how to use [hypermedia links](./020_Links/000_index.md), [link relations](./030_Link-relation-types/000_index.md) and finally [profiles](./040_Profiles/000_index.md) to support [versioning](../050_Compatibility/020_Versioning/000_index.md). diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/000_index.md deleted file mode 100644 index c3c547b..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/000_index.md +++ /dev/null @@ -1,7 +0,0 @@ -# Maturity level - -[Richardson Maturity Model](https://martinfowler.com/articles/richardsonMaturityModel.html) is a well received way to categorize APIs according to REST architectural constraints. - -The last level of this model requires a constraint called HATEOAS (Hypermedia As The Engine Of Application State). This allows API providers to fully control consumer behavior with their responses, so in extreme cases they could even be implemented completely generically. While not practical most of the time, aspects of this last stage can be used to make consumers more independent of business changes to an API. - -Hypermedia is based on the linking of resources that allows consumers to interact with the server with little to no prior knowledge. The links used for this purpose allow navigation without side effects between resources, as well as operations with side effects on resources that are interpreted differently depending on the domain. diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/010_must-implement-rest-maturity-level-2.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/010_must-implement-rest-maturity-level-2.md deleted file mode 100644 index c7753af..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/010_must-implement-rest-maturity-level-2.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -type: MUST -id: R000032 ---- - -# implement REST maturity level 2 - -For all our APIs, we strive for a good implementation of [REST Maturity Level 2](https://martinfowler.com/articles/richardsonMaturityModel.html#level2) as it enables us to build resource-oriented APIs that make full use of HTTP methods and status codes. -This is reflected in many rules of our guidelines, such as: - -- [MUST use nouns to represent resources](@guidelines/R000016) -- [MUST use HTTP methods correctly](@guidelines/R000007) -- [MUST use standard HTTP status codes](@guidelines/R000012) - -Although this is not HATEOAS, it should not prevent you from designing proper link relations in your APIs. - -If you do so, you should use application/hal+json as representation format, because: - -- Later publication of the API will be easier if HAL is used from the beginning. -- Implementing API clients is easier if different parts of the API behave the same and if the same format is used for different purposes. - -References: -- Internet Draft [JSON Hypertext Application Language](https://tools.ietf.org/html/draft-kelly-json-hal-08) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/020_must-implement-rest-maturity-level-3-for-transitional-apis.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/020_must-implement-rest-maturity-level-3-for-transitional-apis.md deleted file mode 100644 index a25c547..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/020_must-implement-rest-maturity-level-3-for-transitional-apis.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -type: MUST -id: R000033 ---- - -# implement REST maturity level 3 for transitional APIs - -Hypermedia must be implemented for [unsafe resource operations](@guidelines/R000008) (e.g. `POST`) that will cause client errors (`4xx`) depending on one of the below mentioned criteria. If one or more of the criteria apply to the cause of error, [REST Maturity Level 3](https://martinfowler.com/articles/richardsonMaturityModel.html#level3) must be implemented in order to: - -- allow clients to reason about the availability of the unsafe resource operation (e.g. for UI button enabling/disabling) before actually invoking it -- prevent duplication of business logic on API provider and consumer side, making business logic changes even harder. - -## Criteria for the error cause - -### State of the resource - -Unsafe resource operations will fail depending on the state of the resource itself. - -`Example`{ label } _Cancellation of an order is only possible as long as it is not shipped. -When error responses are solely caused by the caller's request entity and/or parameter(s), the implementation of hypermedia links is not necessary._ - -### Authorization - -Unsafe resource operations will fail depending on the [authorization](../../005_Authorization/000_index.md) of the calling identity. - -`Example`{ label } _Rating products is only available to customers with a certain reputation._ - -### Time - -Unsafe resource operations will fail depending on the time the resource is accessed. - -`Example`{ label } _Vouchers are only valid for 2 weeks, after that period their usage will lead to errors, though the voucher itself has not changed it's state_ - -References: -- [Unsafe operations](https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.1) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/030_must-use-hal-to-implement-REST-maturity-level-3.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/030_must-use-hal-to-implement-REST-maturity-level-3.md deleted file mode 100644 index 795da26..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/010_Maturity-level/030_must-use-hal-to-implement-REST-maturity-level-3.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -type: MUST -id: R000036 ---- - -# use HAL (Hypertext Application Language) to implement REST maturity level 3 - -This rule applies to APIs that have to comply with [REST maturity level 3](@guidelines/R000033). - -Since a variety of hypermedia formats exists, we decided to use HAL when a hypermedia implementation is required for the following reasons: - -- The simplicity compared to other formats ensures quick familiarization with the format. -- Every `application/json` entity is a valid `application/hal+json` entity. This gives us the possibility to start with any given JSON API and later decide to add hyperlinks and embedded resources in a non-breaking way. - -References: -- Internet Draft [JSON Hypertext Application Language](https://tools.ietf.org/html/draft-kelly-json-hal-08) -- List of [hypermedia formats](https://gtramontina.com/h-factors/) and their H-Factors -- [H-Factors](http://amundsen.com/hypermedia/hfactor/) by Amundsen diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/000_index.md deleted file mode 100644 index 32616bf..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/000_index.md +++ /dev/null @@ -1,5 +0,0 @@ -# Links - -Hypermedia links embedded in an HTTP response allow API providers to communicate dynamic facts, such as business rule outcomes, to consumers independent of any static OpenAPI interface documentation. - -This means that the reasons for these facts do not need to be explicitly stated in the static documentation and therefore do not need to be implemented by consumers. In addition, consumers are not dependent on them, which makes any change much easier. diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/010_must-use-absolute-urls.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/010_must-use-absolute-urls.md deleted file mode 100644 index 59fcf05..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/010_must-use-absolute-urls.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -type: MUST -id: R100032 ---- - -# use absolute URLs - -Links to other resources must always use full, absolute hrefs. If a client supplies -a [`Forwarded` request header](@guidelines/R000044), the -header value must be used for generating absolute URLs. - -The `Forwarded` header may contain the directives `host` and `proto`. The `host` directive contains the `Host` request -field as received by the proxy that forwarded the request. The `proto` directive contains the protocol that was used -to make the request to the proxy (usually `http` or `https`). For the construction of absolute URLs based on the -`Forwarded` Header, the service also needs to take into account the path under which the service is made available -to the client by the reverse proxy. - -Motivation: - -Exposing any form of relative URI (no matter if the relative URI uses an absolute or relative path) -introduces avoidable client side complexity. It also requires clarity on the base URI, which might not be given when -using features like embedding subresources. - -The main advantage of non-absolute URIs is the reduction in payload size, which can be better achieved by following the -recommendation to use gzip compression. - -Example: - -In this example the origin service (serving ) can only be reached through a reverse proxy -which acts as an API gateway (serving ). The client communicates with the origin service through -the API gateway. That is why the origin service can only deduct the client facing URI from the `Forwarded` header. -The `Forwarded` header is set by the API gateway. - -```http request -# Request from the client to the API gateway -GET https://api.otto.de/example-api/my-ressource/1234 -# Proxied request from the API gateway to the origin service -GET https://myExampleService:8080/my-ressource/1234 -Forwarded: for=156.124.2.46;host=api.otto.de;proto=https -``` - -The answer from the origin-services must ues the `host` and `proto` directives of the `Forwarded` header and its API -gateway path to generate absolute URLs: - -```json -{ - ... - "_links" : { - "self" : "https://api.otto.de/example-api/my-ressource/1234", - ... - } -} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/020_should-contain-link-title-attribute.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/020_should-contain-link-title-attribute.md deleted file mode 100644 index 0be3b20..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/020_should-contain-link-title-attribute.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -type: SHOULD -id: R100064 ---- - -# contain link title attribute - -All hyperlinks should have a ['title'](https://tools.ietf.org/html/draft-kelly-json-hal-08#section-5.7) attribute. -The value of the attribute should not contain generic descriptions ('The author'), but should be a specific human-readable name or title of the target resource. - -```json -{ - "_links": { - "author": [ - { - "href": "https://api.otto.de/authors/4711", - "title": "John" - } - ] - } -} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/030_must-contain-deprecation-attribute.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/030_must-contain-deprecation-attribute.md deleted file mode 100644 index b4273c8..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/030_must-contain-deprecation-attribute.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -type: MUST -id: R100065 ---- - -# contain deprecation attribute - -Links to deprecated APIs must contain the optional link attribute ['deprecation'](https://tools.ietf.org/html/draft-kelly-json-hal-08#section-5.4), if applicable. -The value of the deprecation attribute must point to human-readable information about the deprecation. -See also [Deprecation](../../050_Compatibility/040_Deprecation/000_index.md). diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/040_must-provide-conventional-hyperlinks.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/040_must-provide-conventional-hyperlinks.md deleted file mode 100644 index d3530c4..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/040_must-provide-conventional-hyperlinks.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -type: MUST -id: R100033 ---- - -# provide conventional hyperlinks - -This rule applies to APIs that have to comply with [REST maturity level 3](@guidelines/R000033). - -Hyperlinks to other resources [must use HAL](@guidelines/R000036). - -The following links must be contained in HAL representations: - -- `self`: The _canonical_ hyperlink of the resource. -- `profile`: The fully qualified link pointing to the `profile` of the resource, if any. The link [must resolve to some - human-readable documentation](@guidelines/R100066) of the profile. The `profile` is omitted - if the resource does not have any custom properties beside HAL `_links` and `_embedded` elements. [Collection - resources](../../030_Resources/020_Collection-resources/000_index.md), for example, might only be plain `application/hal+json` - representations without any custom attributes. -- `collection`: For items contained in a collection resource, this link should point to the collection. In most cases, this - link will be [templated](https://tools.ietf.org/html/draft-kelly-json-hal-08#section-5.2). -- `search`: For searchable collection resources, a [templated](https://tools.ietf.org/html/draft-kelly-json-hal-08#section-5.2) link should be added that refers to the collection including all template parameters. - -Example of a [paged collection](@guidelines/R100025) resource: - -```json -{ - "_links": { - "self": { "href": "https://api.otto.de/orders?page=2&pageSize=10" }, - "profile": { - "href": "https://api.otto.de/portal/profiles/orders/paged-collection+v1" - }, - "search": { - "href": "https://api.otto.de/orders{?q,page,pageSize}", - "templated": true - }, - "item": [{ "href": "https://api.otto.de/orders/4711" }] - }, - "_page": { - "size": 10, - "number": 2, - "totalElements": 21, - "totalPages": 3 - } -} -``` - -Example of a `collection item`: - -```json -{ - "_links": { - "self": { "href": "https://api.otto.de/orders/4711" }, - "profile": { - "href": "https://api.otto.de/portal/profiles/orders/order+v1" - }, - "collection": { - "href": "https://api.otto.de/orders{?q,page,pageSize}", - "templated": true - } - }, - "total": 3000, - "currency": "EUR", - "status": "shipped" -} -``` - -References: -- [MUST implement REST maturity level 2](@guidelines/R000032) -- [MUST implement REST maturity level 3 for transitional APIs](@guidelines/R000033) -- [MUST support hypermedia controls in collection resources](@guidelines/R100026) -- [Link-Relation Types](../030_Link-relation-types/000_index.md) -- [IANA link relations](http://www.iana.org/assignments/link-relations/link-relations.xhtml) -- [REST lesson learned: consider a self link on all resources](https://blog.ploeh.dk/2013/05/03/rest-lesson-learned-consider-a-self-link-on-all-resources/) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/050_must-not-use-link-headers-for-json-representations.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/050_must-not-use-link-headers-for-json-representations.md deleted file mode 100644 index ddc1659..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/050_must-not-use-link-headers-for-json-representations.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -type: MUST NOT -id: R100034 -reviewType: automatic ---- - -# use link headers for JSON representations - -For flexibility and precision, we prefer links to be directly embedded in the JSON payload instead of being attached using the uncommon link header syntax. -As a result, the use of the `Link` header defined by [RFC 8288](https://tools.ietf.org/html/rfc8288#section-3) in conjunction with JSON media types is not allowed. diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/060_must-support-forwarded-header.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/060_must-support-forwarded-header.md deleted file mode 100644 index b273286..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/060_must-support-forwarded-header.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -type: MUST -id: R000044 ---- - -# support `Forwarded` header - -In order to support proxies in front of your origin server, you must implement support for the `Fowarded` request header. - -The `Forwarded` header is defined in [RFC 7239](https://tools.ietf.org/html/rfc7239) for identifying e.g. the original host (and port) requested by the client in the `Host` HTTP request header or the specified protocol. -Consult [RFC 7239, Section 4](https://tools.ietf.org/html/rfc7239#section-4) for examples of this header. - -[Absolute URLs](@guidelines/R100032) rendered in links of a HAL response contain the value of this header. diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/070_must-contain-separate-id-field-in-the-payload.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/070_must-contain-separate-id-field-in-the-payload.md deleted file mode 100644 index a0bc860..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/070_must-contain-separate-id-field-in-the-payload.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -type: MUST -id: R000061 ---- - -# contain a separate ID field in the payload - -The payload of a resource must always contain the technical ID for the client, so that it can be reused without parsing it from the links. - -Read [Relative vs. Absolute links (internal link)](https://github.com/otto-ec/ottoapi_guidelines/blob/master/references/relative-vs-absolute-uris.md) for further information on this topic. diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/080_must-support-hypermedia-controls-in-collection-resources.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/080_must-support-hypermedia-controls-in-collection-resources.md deleted file mode 100644 index aa352ac..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/080_must-support-hypermedia-controls-in-collection-resources.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -type: MUST -id: R100026 ---- - -# support hypermedia controls in collection resources - -This rule applies to APIs that have to comply with [REST maturity level 3](@guidelines/R000033). - -Provide links to navigate the result. Clients must be able to navigate the collection without additional knowledge. If the link is present, it must point to a valid segment of the collection resource. -The [IANA link relations](http://www.iana.org/assignments/link-relations/link-relations.xhtml) must be used whenever applicable. - -The most common ones are: - -- `self` : the current page -- `next` (_optional_): the next page. Should be set, only if next page is present. -- `prev` (_optional_): the previous page, if present. Must be omitted for the first page. -- `first` (_optional_): the first page -- `last` (_optional_): the last page - -Some properties like `first`, `next` and `last` can be omitted if the implementation is not feasable, for example, when the calculation has a big performance impact. -Exposing this data should consider the performance implications, not only now but over the lifespan of the service. - -References: -- [MUST implement REST maturity level 2](@guidelines/R000032) -- [MUST implement REST maturity level 3 for transitional APIs](@guidelines/R000033) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/090_must-contain-links-for-embedded-resources.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/090_must-contain-links-for-embedded-resources.md deleted file mode 100644 index ed2906a..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/090_must-contain-links-for-embedded-resources.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -type: MUST -id: R000042 ---- - -# contain links for embedded resources - -This rule applies to APIs that have to comply with [REST maturity level 3](@guidelines/R000033). - -Servers must not entirely "swap out" a link for an embedded resource (or vice versa) because client support for this technique is OPTIONAL. - -For every embedded resource, a corresponding link MUST be contained in the `_links` object of the embedding resource. - -Example: - -```http request -GET https://api.otto.de/products HTTP/1.1 -``` - -```json -{ - "_links": { - "item": [{ "href": "http://api.otto.de/products/4711" }] - }, - "_embedded": { - "item": [ - { - "_links": { - "self": [{ "href": "http://api.otto.de/products/4711" }] - }, - "productId": "4711" - } - ] - } -} -``` - -But do not render the item like this: - -```http request -GET https://api.otto.de/products HTTP/1.1 -``` - -```json -{ - "_links": { - "item": [{ "href": "http://api.otto.de/products/4711" }] - }, - "_embedded": { - "item": [ - { - "productId": "4711" - } - ] - } -} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/100_should-provide-hypermedia-links-in-embedded-documents.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/100_should-provide-hypermedia-links-in-embedded-documents.md deleted file mode 100644 index 7f0324e..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/020_Links/100_should-provide-hypermedia-links-in-embedded-documents.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -type: SHOULD -id: R100028 ---- - -# provide hypermedia links in embedded documents - -The list resource items should provide the same links as the single resource representation as described in [Hypermedia](../000_index.md). - -Links may be omitted to prevent performance degradation or response bloat. -Keep the client's use cases in mind. -You should not omit information if most use cases need those and would be forced to do `n` additional calls. diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/000_index.md deleted file mode 100644 index de6117c..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/000_index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Link relation types - -A link relation is a descriptive attribute attached to a hyperlink in order to define the type of the link or the relationship between the source and destination resources. diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/010_must-prefer-existing-custom-link-relation-types.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/010_must-prefer-existing-custom-link-relation-types.md deleted file mode 100644 index 694b883..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/010_must-prefer-existing-custom-link-relation-types.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -type: MUST -id: R100035 ---- - -# prefer existing custom link relation types - -This rule applies to APIs that have to comply with [REST maturity level 3](@guidelines/R000033). - -Already specified [custom link relation types](@guidelines/R100037) must be used instead of introducing new ones if the specified semantics are applicable. - -References: -- [MUST implement REST maturity level 2](@guidelines/R000032) -- [MUST implement REST maturity level 3 for transitional APIs](@guidelines/R000033) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/020_must-prefer-iana-registered-link-relation-types.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/020_must-prefer-iana-registered-link-relation-types.md deleted file mode 100644 index c763b32..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/020_must-prefer-iana-registered-link-relation-types.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -type: MUST -id: R100036 ---- - -# prefer IANA-registered link relation types - -This rule applies to APIs that have to comply with [REST maturity level 3](@guidelines/R000033). - -Instead of defining [custom link relation types](@guidelines/R100037), -[IANA-registered](http://www.iana.org/assignments/link-relations/link-relations.xhtml) link relation types must be used, if the specified semantics are applicable. - -Only if a more specific custom link relation type already exists, the custom option should be preferred. -For example, the collection of all products should use `o:product` instead of `item`. -A link relation type `o:author` must not be defined, because the IANA registry already defines `author`. - -References: -- [MUST implement REST maturity level 2](@guidelines/R000032) -- [MUST implement REST maturity level 3 for transitional APIs](@guidelines/R000033) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/030_must-use-absolute-urls-for-custom-link-relation-types.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/030_must-use-absolute-urls-for-custom-link-relation-types.md deleted file mode 100644 index 65b5fb2..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/030_must-use-absolute-urls-for-custom-link-relation-types.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -type: MUST -id: R100037 ---- - -# use absolute URLs for custom link relation types - -This rule applies to APIs that have to comply with [REST maturity level 3](@guidelines/R000033). - -If no [IANA-registered](http://www.iana.org/assignments/link-relations/link-relations.xhtml) link relation type is applicable and no [existing custom link relation type](@guidelines/R100035) can be used instead, a custom link relation type can be introduced. - -Custom link relations must comply with the following rules: - -- Custom link relation types must have a fully qualified URL. -- The URL must be resolvable using the URI template `https://api.otto.de/portal/link-relations/{context-id}/{rel}`. -- Just as with [profile URLs](@guidelines/R100066), link relation URLs must contain exactly one `context-id`. Context information prevent name collisions and allow grouping of link relations by domain. -- In the URL, `context-id` and `rel` must be kebab-case. -- Custom link relation types must be documented. -- The documentation must be accessible in a human-readable format using the URL of the link relation type. - -Using a link relation type such as `"variation": {"href":"https://api.otto.de/variations/4711"}` is therefore not allowed. - -References: -- [MUST implement REST maturity level 2](@guidelines/R000032) -- [MUST implement REST maturity level 3 for transitional APIs](@guidelines/R000033) -- [MUST use curied link relation types](@guidelines/R100038) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/040_must-use-curied-link-relation-types.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/040_must-use-curied-link-relation-types.md deleted file mode 100644 index 9bdb7c6..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/040_must-use-curied-link-relation-types.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -type: MUST -id: R100038 ---- - -# use curied link relation types - -This rule applies to APIs that have to comply with [REST maturity level 3](@guidelines/R000033). - -Custom link relation types can be introduced if no [IANA-registered](@guidelines/R100036) or [existing custom](@guidelines/R100035) link relation type matches the semantics of a link. -In this case, the rule [MUST use absolute URLs for custom link relation types](@guidelines/R100037) must be adhered to. - -A resource that uses custom link relation types to link to other resources must have a `curies` array in its `_links` property. OTTO API curie objects inside this array must have the property `href` with a value in the form of `https://api.otto.de/portal/link-relations/{context-id}/{rel}`. - -```json -{ - "_links": { - "self": { "href": "https://api.otto.de/orders?page=2&pageSize=10" }, - "curies": [ - { - "name": "o", - "href": "https://api.otto.de/portal/link-relations/orders/{rel}", - "templated": true - } - ] - } -} -``` - -Links to a resource with a custom link relation type must be curied using this CURI: - -```json -{ - "_links": { - "self": { "href": "https://api.otto.de/orders?page=2&pageSize=10" }, - "curies": [ - { - "name": "o", - "href": "https://api.otto.de/portal/link-relations/orders/{rel}", - "templated": true - } - ], - "o:order": [ - { "href": "https://api.otto.de/orders/4711" }, - { "href": "https://api.otto.de/orders/0815" } - ] - } -} -``` - -If the linked resources [can be embedded](@guidelines/R000041) into the response, the service should use the same link relation type that is used to link the subresources: - -```json -{ - "_links": { - "self": { "href": "https://api.otto.de/orders?page=2&pageSize=10" }, - "curies": [ - { - "name": "o", - "href": "https://api.otto.de/portal/link-relations/orders/{rel}", - "templated": true - } - ], - "o:order": [ - { "href": "https://api.otto.de/orders/4711" }, - { "href": "https://api.otto.de/orders/0815" } - ] - }, - "_embedded": { - "o:order": [ - { - "_links": { - "self": { "href": "https://api.otto.de/orders/4711" }, - "collection": { "href": "https://api.otto.de/orders" } - }, - "id": "4711", - "total": 4200 - }, - { - "_links": { - "self": { "href": "https://api.otto.de/orders/0815" }, - "collection": { "href": "https://api.otto.de/orders" } - }, - "id": "0815", - "total": 12900 - } - ] - } -} -``` - -References: -- [MUST implement REST maturity level 2](@guidelines/R000032) -- [MUST implement REST maturity level 3 for transitional APIs](@guidelines/R000033) -- [MUST prefer IANA-registered link relation types](@guidelines/R100036) -- [MUST prefer existing custom link relation types](@guidelines/R100035) -- [MUST use absolute URLs for custom link relation types](@guidelines/R100037) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/050_must-document-link-cardinality.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/050_must-document-link-cardinality.md deleted file mode 100644 index 380417f..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/030_Link-relation-types/050_must-document-link-cardinality.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -type: MUST -id: R100063 ---- - -# document link cardinality - -This rule applies to APIs, that have to comply with [REST maturity level 3](@guidelines/R000033). - -The HAL `_links` object holds property names of link relation types, and values of either a link object: - -```json -{ - "_links": { - "author": { "href": "http://api.otto.de/users/42" } - } -} -``` - -...or an array of link objects: - -```json -{ - "_links": { - "item": [ - { "href": "http://api.otto.de/products/4711" }, - { "href": "http://api.otto.de/products/0815" } - ] - } -} -``` - -In order to simplify the implementation of API clients, the client must know which link relation types contain single link objects, and which contain an array of link objects. -Thats why every profile must document the cardinality of the link relation types used in the profile. - -References: -- [MUST implement REST maturity level 2](@guidelines/R000032) -- [MUST implement REST maturity level 3 for transitional APIs](@guidelines/R000033) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/000_index.md deleted file mode 100644 index ccad5e3..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/000_index.md +++ /dev/null @@ -1,81 +0,0 @@ -# Profiles - -The OTTO APIs must either support `application/json` or `application/hal+json` as a media type. -As these formats are not specific enough for our purposes, all APIs [must be documented](@guidelines/R000003) -using [OpenAPI Spec 3.0](http://spec.openapis.org/oas/v3.0.3). - -## Using profiles - -A `product` representation, for example, might use `application/hal+json` as a media type. -Using OpenAPI Spec, the structure of the representation must be specified, so that developers of an API client know about the different properties of the `product`. - -Depending on the context, the same domain object may have several representations. For example, `product` as a search result might contain information such as availability or delivery options. `product` as part of the processed customer order shares some essential details with the search result, but would likely contain some other attributes instead. Therefore, different perspectives on the same business object may result in different representations. - -The specification must be identifiable by a URL such as `https://api.otto.de/portal/profiles/products/product+v1`. -If later a second version of the `product` representation is added, the new version of the spec (`https://api.otto.de/portal/profiles/products/product+v2`) can be distinguished from the earlier version. - -Using the [`Accept` header with profile parameter](@guidelines/R000030), clients can now specify the requested version of the specification like this: - -```http request -GET https://api.otto.de/products/42 HTTP/1.1 -Accept: application/hal+json; profile="https://api.otto.de/portal/profiles/products/product+v1" -``` - -The returned `product` representation (an `application/hal+json` document) [must contain a link](@guidelines/R100033) to the profile: - -```json -{ - "_links": { - "self": { "href": "https://api.otto.de/products/42" }, - "profile": { - "href": "https://api.otto.de/portal/profiles/products/product+v1" - } - }, - "etc": "..." -} -``` - -[Following the `profile` link](@guidelines/R100066), an API client developer can now find the human-readable specification of the returned document. - -In many cases, the representation of a HAL resource contains hyperlinks to other resources. -In our case, the representation might contain N links to product images (using a link relation type such as `o:product-image`) and a single link to a resource containing customer reviews (using the link relation type `o:customer-reviews`): - -```json -{ - "_links": { - "curies": [ - { - "name": "o", - "href": "https://api.otto.de/portal/link-relations/products/{rel}", - "templated": true - } - ], - "self": { "href": "https://api.otto.de/products/42" }, - "profile": { - "href": "https://api.otto.de/portal/profiles/products/product+v1" - }, - "o:customer-reviews": { "href": "https://api.otto.de/customer-reviews/42" }, - "o:product-images": [ - { "href": "https://i.otto.de/42.jpg" }, - { "href": "https://i.otto.de/43.jpg" } - ] - }, - "etc": "..." -} -``` - -As links may either contain a single link or an array of links, the specification of the `product` representation -[must be explicit](@guidelines/R100063), whether `o:customer-reviews` contains a single link or an array of links. - -Profiles may also apply to request bodies: all public endpoints which accept requests with a body must support request versioning. Currently, this implicates POST, PUT, and PATCH, but other HTTP methods may follow. - -Even though the `profile` parameter is only defined for the media type `application/hal+json`, we chose to also use it for content type based versioning of other media types such as `application/json` and `application/json-patch+json`. This ensures a consistent usage of the `profile` parameter across all used media types. - -References: -- [The 'profile' Link Relation Type (RFC 9606)](https://tools.ietf.org/html/rfc6906) -- [SHOULD use `Accept` and `Content-Type` headers with profile parameter](@guidelines/R000030) -- [MUST provide conventional hyperlinks](@guidelines/R100033) -- [Paged collection](@guidelines/R100023) -- [MUST use profiles for Public APIs](../../050_Compatibility/020_Versioning/010_must-use-profiles-for-public-rest-apis.md) -- Parameters in `application/json` [RFC 7159, Section 11](https://datatracker.ietf.org/doc/html/rfc7159#section-11) -- Parameters in `application/json-patch+json` [RFC 6902, Section 6](https://datatracker.ietf.org/doc/html/rfc6902#section-6) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/010_must-use-resolvable-profile-urls.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/010_must-use-resolvable-profile-urls.md deleted file mode 100644 index 5b116d0..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/010_must-use-resolvable-profile-urls.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -type: MUST -id: R100066 ---- - -# use resolvable profile URLs - -To avoid name collisions for different domains and to allow grouping of profiles within the same context, the profile URI uses a `context-id`. -The URI that identifies a profile must be resolvable and must match `https://api.otto.de/portal/profiles/{context-id}/{name}+v{version}`. - -Profile URIs must comply with the following conventions: - -- must contain exactly one `context-id` -- `context-id` and `name` should be kebab-case -- use plurals or _list_ to indicate a collection, e.g. `https://api.otto.de/portal/profiles/search/products+v1`. -- must not contain team, task or use case shortcuts -- must not contain trailing slashes - -The URL must point to a human-readable documentation of the profile. - -If the API uses [HAL](@guidelines/R000036), the `_links` of the representation [should contain a `profile` link](@guidelines/R100033) with an `href` containing the URL of the representation's profile: - -```json -{ - "_links": { - "self": { "href": "https://api.otto.de/orders/4711" }, - "profile": { - "href": "https://api.otto.de/portal/profiles/checkout/order+v1" - } - }, - "total": 3000, - "currency": "EUR", - "status": "shipped" -} -``` - -References: -- [MUST implement REST maturity level 2](@guidelines/R000032) -- [MUST implement REST maturity level 3 for transitional APIs](@guidelines/R000033) -- [MUST provide conventional hyperlinks](@guidelines/R100033) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/020_must-use-kebab-case-profile-uris.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/020_must-use-kebab-case-profile-uris.md deleted file mode 100644 index 68d1985..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/020_must-use-kebab-case-profile-uris.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -type: MUST -id: R100070 ---- - -# use kebab-case profile URIs - -Just like [other URIs](@guidelines/R000023), profile URIs must be kebab-case (and not camelCase). - -References: -- [MUST use resolvable profile URLs](@guidelines/R100066) -- [MUST use kebab-case for URIs](@guidelines/R000023) diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/030_must-provide-openapi-spec-for-profiles.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/030_must-provide-openapi-spec-for-profiles.md deleted file mode 100644 index 4fd7830..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/030_must-provide-openapi-spec-for-profiles.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -type: MUST -id: R100067 ---- - -# provide OpenAPI Spec for profiles - -Profiles must be specified using an OpenAPI specification, for example, by using `schemas` in a `components` block. - -Every version of a profile must be a separate model entity inside of the `components` block -identified by a unique ID, which includes a version string. diff --git a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/040_may-use-type-and-profile-attributes-in-hyperlinks.md b/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/040_may-use-type-and-profile-attributes-in-hyperlinks.md deleted file mode 100644 index f7ae6e2..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/020_Hypermedia/040_Profiles/040_may-use-type-and-profile-attributes-in-hyperlinks.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -type: MAY -id: R100068 ---- - -# use type and profile attributes in hyperlinks - -The HAL `_links` object's property names are link relation types and values are either a link object or an array of link objects. - -Beside others, HAL links may contain the optional attributes ['type'](https://tools.ietf.org/html/draft-kelly-json-hal-08#section-5.3) or ['profile'](https://tools.ietf.org/html/draft-kelly-json-hal-08#section-5.6) - -As [versioning](../../050_Compatibility/020_Versioning/000_index.md) of APIs [should be implemented using `Accept` and `Content-Type` headers with profile parameter](@guidelines/R000030), HAL representations of a resource may use `type` and `profile` to specify the mediatype and profile of a linked resource. - -```json -{ - "_links": { - "author": [ - { - "href": "https://api.otto.de/authors/4711", - "type": "application/hal+json", - "profile": "https://api.otto.de/portal/profiles/authors/person+v1" - } - ] - } -} -``` - -While using the profile parameter improves the discoverability of the API (because the [link of the profile points to a human-readable documentation](@guidelines/R100066)), adding a new profile requires the API to add links for every profile: - -```json -{ - "_links": { - "author": [ - { - "href": "https://api.otto.de/authors/4711", - "type": "application/hal+json", - "profile": "https://api.otto.de/portal/profiles/authors/person+v1" - }, - { - "href": "https://api.otto.de/authors/4711", - "type": "application/hal+json", - "profile": "https://api.otto.de/portal/profiles/authors/person+v2" - } - ] - } -} -``` - -Sometimes resources may link to other resources that are available in multiple mediatypes such as JSON and HTML, or JSON and XML. -In this case, the API should use the type attribute in hyperlinks: - -```json -{ - "_links": { - "o:product": [ - { - "href": "https://api.otto.de/products/4711", - "type": "application/hal+json" - }, - { - "href": "https://www.otto.de/p/4711", - "type": "text/html" - } - ] - } -} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/000_index.md deleted file mode 100644 index 3c1229e..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# Resources diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/000_index.md deleted file mode 100644 index d32b432..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/000_index.md +++ /dev/null @@ -1,40 +0,0 @@ -# Embedded resources - -The "hypertext cache pattern" allows servers to use embedded resources to dynamically reduce the number of requests a client makes, improving the efficiency and performance of the application. -Clients should be automated for this purpose so that, for any given link relation, they will read from an embedded resource (if present) in preference to traversing a link. -To activate this client behavior for a given link, servers should add an embedded resource into the representation with the same relation. -Servers should not entirely "swap out" a link for an embedded resource (or vice versa) because client support for this technique is OPTIONAL. - -## Example - -The following examples show the hypertext cache pattern applied to an "author" link: - -_Before:_ - -```json -{ - "_links": { - "self": { "href": "/books/the-way-of-zen" }, - "author": { "href": "/people/alan-watts" } - } -} -``` - -_After:_ - -```json -{ - "_links": { - "self": { "href": "/blog-post" }, - "author": { "href": "/people/alan-watts" } - }, - "_embedded": { - "author": { - "_links": { "self": { "href": "/people/alan-watts" } }, - "name": "Alan Watts", - "born": "January 6, 1915", - "died": "November 16, 1973" - } - } -} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/010_should-embed-subresources.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/010_should-embed-subresources.md deleted file mode 100644 index d9fad43..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/010_should-embed-subresources.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -type: SHOULD -id: R000041 ---- - -# embed subresources - -Embedding related resources (also known as resource expansion) is a great way to reduce the number of requests. -Resources that link to subresources should return these subresources using the HAL `_embedded` object. - -Do not embed a resource or at least embed it optional (via embed query param), if it generates unnecessary load, traffic, or response bloat. - -Example: - -```http request -GET https://api.otto.de/products HTTP/1.1 -``` - -```json -{ - "_links": { - "item": [{ "href": "http://api.otto.de/products/4711" }] - }, - "_embedded": { - "item": [ - { - "productId": "4711", - "price": { - "amount": 71.99, - "currency": "EUR" - } - } - ] - } -} -``` - -References: -- [SHOULD support optional embedding of subresources](@guidelines/R000063) diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/020_should-support-optional-embedding-of-subresources.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/020_should-support-optional-embedding-of-subresources.md deleted file mode 100644 index 8697e0a..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/020_should-support-optional-embedding-of-subresources.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -type: SHOULD -id: R000063 ---- - -# support optional embedding of subresources - -Resources that link to subresources [SHOULD support embedding of subresources](@guidelines/R000041). -In order to improve flexibility of the API for different use cases, embedding of subresources should be optional, using the request parameter [`embed`](@guidelines/R000049) to select the -subresources to embed. - -In cases where clients know upfront that they need some related resources they can instruct the server to prefetch that data eagerly. -Whether this is optimized on the server, for example, by a database join, or done in a generic way, for example, with an HTTP proxy that transparently embeds resources, is up to the implementation. - -Example: - -```http request -GET https://api.otto.de/products?embed=(item) HTTP/1.1 -``` - -```json -{ - "_links": { - "item": [{ "href": "http://api.otto.de/products/4711" }] - }, - "_embedded": { - "item": [ - { - "_links": { - "self": [{ "href": "http://api.otto.de/products/4711" }] - }, - "productId": "4711", - "price": { - "amount": 71.99, - "currency": "EUR" - } - } - ] - } -} -``` - -If parameter `embed` is not provided by the client, the resources should be embedded by default. -However, clients could also decide to NOT embed the linked resources: - -```http request -GET https://api.otto.de/products?embed=() HTTP/1.1 -``` - -```json -{ - "_links": { - "item": [{ "href": "http://api.otto.de/products/4711" }] - } -} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/040_should-read-embedded-resources-instead-of-traversing-links.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/040_should-read-embedded-resources-instead-of-traversing-links.md deleted file mode 100644 index 60b3f87..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/040_should-read-embedded-resources-instead-of-traversing-links.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -type: SHOULD -id: R000043 ---- - -# read embedded resources instead of traversing links - -For any given link relation, clients of an API should be automated to read from an embedded resource (if present) in preference to traversing a link. - -If supported by the API, clients should use the common request parameter -[`embed`](@guidelines/R000049) to select the subresources they are interested in. - -References: -- [SHOULD embed subresources](@guidelines/R000041) -- [SHOULD support optional embedding of subresources](@guidelines/R000063) diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/050_must-use-hal-format-for-embedded-resources.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/050_must-use-hal-format-for-embedded-resources.md deleted file mode 100644 index 78b403c..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/010_Embedded-resources/050_must-use-hal-format-for-embedded-resources.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -type: MUST -id: R000045 ---- - -# use HAL format for embedded resources - -This rule applies to APIs that have to comply with [REST maturity level 3](@guidelines/R000033). - -If [HAL is mandatory](@guidelines/R000036) is mandatory, subresources must be embedded the same format. - -References: -- [MUST implement REST maturity level 2](@guidelines/R000032) -- [MUST implement REST maturity level 3 for transitional APIs](@guidelines/R000033) diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/000_index.md deleted file mode 100644 index 059762b..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/000_index.md +++ /dev/null @@ -1,4 +0,0 @@ -# Collection resources - -A collection resource represents a list of resources such as the collection of all products. -The response may contain additional top level fields and metadata. diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/010_must-use-plural-for-collection-resources.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/010_must-use-plural-for-collection-resources.md deleted file mode 100644 index 2831915..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/010_must-use-plural-for-collection-resources.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -type: MUST -id: R100020 ---- - -# use plural for collection resources - -If a resource can be identified as a collection resource, such as `order`, use the plural for resource naming: - -`/orders` - -If we want to identify a single customer resource, this is what we do: - -`/orders/{orderId}` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/020_must-use-hal-format-for-collection-resource.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/020_must-use-hal-format-for-collection-resource.md deleted file mode 100644 index 9cd7ece..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/020_must-use-hal-format-for-collection-resource.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -type: MUST -id: R100021 ---- - -# use HAL format for collection resources - -This rule applies to APIs that have to comply with [REST maturity level 3](@guidelines/R000033). - -The list of resources is embedded under `_embedded` with the key representing the link-relation type. -This is the same as the one used in the `_links` section. - -The [Embedded resources](../010_Embedded-resources/000_index.md) section provides more information on embedding documents. - -References: -- [MUST implement REST maturity level 2](@guidelines/R000032) -- [MUST implement REST maturity level 3 for transitional APIs](@guidelines/R000033) diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/030_must-support-pagination-for-collection-resources.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/030_must-support-pagination-for-collection-resources.md deleted file mode 100644 index 1e1e1fc..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/030_must-support-pagination-for-collection-resources.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -type: MUST -id: R100023 ---- - -# support pagination for collection resources - -Any sufficiently large collection resource must support pagination to handle the server load and support the client processing patterns. - -There are two approaches to pagination: - -- Offset/Limit-based pagination -- Cursor-based pagination - -Choosing the right approach depends entirely on the constraints of the service. -There is no preference of which one to choose, they both have their advantages. - -## Offset/limit-based pagination -Offset or limit-based pagination allows the navigation of the result by specifying an offset. -This kind of pagination is ususally implemented as page-based pagination, that means, the result set is further divided into pages of a certain size and you navigate by providing the page number instead of just an offset. -This is the most common approach to do pagination, especially for traditional RDBM systems. - -PROs - -- well-known pattern -- wide support for server and client - -CONs - -- assumes fixed length / fixed window: next page might contain previous elements or skip elements if elements were inserted or deleted in the meantime. - Should be avoided for frequently updated collections. - -Example: - -```json -{ - "_links": { - "item": [ - { "href": "https://api.otto.de/orders/123" }, - { "href": "https://api.otto.de/orders/124" } - ], - "prev": { "href": "https://api.otto.de/orders?page=1" }, - "self": { "href": "https://api.otto.de/orders?page=2" }, - "next": { "href": "https://api.otto.de/orders?page=3" }, - "first": { "href": "https://api.otto.de/orders" }, - "last": { "href": "https://api.otto.de/orders?page=9" } - }, - "_embedded": { - "item": [ - { - "total": 30.0, - "currency": "USD", - "status": "shipped", - - "_links": { - "self": { "href": "https://api.otto.de/orders/123" } - } - }, - { - "total": 20.0, - "currency": "USD", - "status": "processing", - - "_links": { - "self": { "href": "https://api.otto.de/orders/124" } - } - } - ] - }, - - "_page": { - "size": 10, - "totalElements": 100, - "totalPages": 1, - "number": 0 - }, - - "currentlyProcessing": 14, - "shippedToday": 20 -} -``` - -## Cursor-based pagination -Cursor-based pagination is often preferred, especially when data sets increase quickly. - -PROs - -- window moves: next page always refers to the following elements, even if new elements are prepended in the meantime - -CONs - -- not well-known -- limited support for clients -- cursor might be invalid if the entry is deleted, breaking iteration - -Example: - -```json -{ - "_links": { - "self": { - "href": "https://api.otto.de/orders?after=532d39e987409c5b6fe7f913c9e568af" - }, - "item": [ - { "href": "https://api.otto.de/orders/123" }, - { "href": "https://api.otto.de/orders/124" } - ], - "prev": { - "href": "https://api.otto.de/orders?before=911d39e987409c5b6fe7f913c9e568ca" - }, - "next": { - "href": "https://api.otto.de/orders?after=40770e2e3ce129faadd08663fa434c33" - }, - "first": { "href": "https://api.otto.de/orders" } - }, - "_embedded": { - "item": [ - { - "total": 30.0, - "currency": "USD", - "status": "shipped", - - "_links": { - "self": { "href": "https://api.otto.de/orders/123" } - } - }, - { - "total": 20.0, - "currency": "USD", - "status": "processing", - - "_links": { - "self": { "href": "/orders/124" } - } - } - ] - }, - - "currentlyProcessing": 14, - "shippedToday": 20 -} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/040_must-use-common-paging-query-parameters.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/040_must-use-common-paging-query-parameters.md deleted file mode 100644 index b7b69cc..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/040_must-use-common-paging-query-parameters.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -type: MUST -id: R100024 ---- - -# use common paging query parameters - -This rule applies to public APIs. For private APIs it should be followed. - -For offset-based pagination you must stick to the following query parameters: - -- `pageSize`: Number of elements in the response or the chunk size -- `page`: Page number that is requested (0-indexed) - -Requested pages outside the valid range (e.g. page 10 of a 5-element collection) must return an empty collection. - -For cursor-based pagination we _recommend_ using the following query parameters: - -- `after`: Results after the cursor position -- `before`: Results before the cursor position - -References: -- [MUST stick to conventional query parameters](@guidelines/R000049) -- [MUST support pagination](@guidelines/R100023) diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/050_should-define-default-and-max-page-size.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/050_should-define-default-and-max-page-size.md deleted file mode 100644 index 56b1535..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/050_should-define-default-and-max-page-size.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -type: SHOULD -id: R100039 ---- - -# define default and maximum page size - -Every collection resource should define and document - -- a reasonable default page size (`defaultPageSize`) -- a maximum page size (`maxPageSize`) - -which can be used as the `pageSize` query parameter. - -References: -- [MUST stick to conventional query parameters](@guidelines/R000049). diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/060_must-provide-page-metadata-for-offset-based-pagination.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/060_must-provide-page-metadata-for-offset-based-pagination.md deleted file mode 100644 index 7938aed..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/060_must-provide-page-metadata-for-offset-based-pagination.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -type: MUST -id: R100025 ---- - -# provide page metadata for offset-based pagination - -Page metadata is important for clients that build their own links and do not use hypermedia controls. - -The page metadata structure must match the following structure. - -```json -{ - "_page": { - "size": 5, - "number": 0, - "totalElements": 50, - "totalPages": 10 - } -} -``` - -- `size` : Maximum number of elements in the response -- `number` : Current page number (0 indexed) -- `totalElements` (_optional_): Overall number of elements -- `totalPages` (_optional_): Overall number of pages - -Some fields like `totalElements` and `totalPages` can be omitted if the implementation is not feasable, for example, when the calculation has a big performance impact. -Exposing this data should consider the performance implications, not only now but over the lifespan of the service. diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/090_must-use-common-sorting-query-parameter.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/090_must-use-common-sorting-query-parameter.md deleted file mode 100644 index 79bdf53..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/090_must-use-common-sorting-query-parameter.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -type: MUST -id: R100030 ---- - -# use common sorting query parameter - -If simple sorting of the results is possible, the `sort` query parameter must be used. - -- The parameter accepts a property and an optional direction suffix (e.g. `sort=price:desc`). - The direction suffix can be `asc` or `desc` in any word case, i.e. `desc`. `dEsC`, `DESC` are all valid. -- The property name should correspond to the name used in the resource representation (e.g. `sort=price.grossValue`). -- Multiple sorting criteria [must be provided as a comma-separated list](@guidelines/R000062) (e.g. `sort=price:asc,name:desc`). -- Services do not need to support all resource properties to be used for sorting and must respond with a `400 Bad Request` if they do not. -- If the use case cannot be expressed using this simple sorting parameter, you should introduce a separate query parameter or a separate endpoint that accepts a complex filter/query language as a JSON body instead of a query parameter. - -`Note`{ label } Make sure to add the `sort` parameter to the to HAL links if necessary. - -References: -- [MUST stick to conventional query parameters](@guidelines/R000049) diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/100_must-use-query-parameters-for-basic-search-or-filtering.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/100_must-use-query-parameters-for-basic-search-or-filtering.md deleted file mode 100644 index 8eea712..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/100_must-use-query-parameters-for-basic-search-or-filtering.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -type: MUST -id: R100031 ---- - -# use query parameters for basic search or filtering - -Resource-specific query parameters may be introduced for querying. -They should reference the property and the operation if necessary. - -- `brand=Adidas`: Property `brand` matches `Adidas` -- `minColors=5`: Either property `colors` or the computed number of colors (e.g. the resource only includes an array of colors) needs to be greater than `5` -- `releasedAfter=2020-02-02`: Release date needs to be after `2020-02-02` - -Different types may have different interpretations of equality, or have their own set of operators. -For example`color=blue` may include any shades of blue and also match `aquamarine`. `maxOrderStatus=PACKED` may include all items that are packed, in delivery or already delivered. - -Use common terminology, e.g. - -- negation: `not` -- value ranges: `max`, `min` -- dates: `before`, `after` - -For basic querying capabilities that are not specific to a property but the whole resource the `q` parameter should be used. -Usually this is a simple text query, satisfying simple search needs that might cover a lot of use cases. - -Query parameters should be combinable (e.g. `brand=Puma&color=blue`) and otherwise respond with a `400 Bad Request`. - -If multiple values need to be supported, they [should be provided as a comma-separated list](@guidelines/R000062) (e.g. `brand=Adidas,Puma`). - -These query parameters must be documented with their possible values (ranges), semantics and interactions with other query parameters (e.g. multiple values form a logical _or_, but with other query parameters an _and_ connection). -This may be obvious for single valued properties, but not necessarily for lists (e.g. `tags=sporty,retro`) - -`Note`{ label } Make sure to add the query parameters to the to HAL links if necessary. - -References: -- [MUST stick to conventional query parameters](@guidelines/R000049) diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/110_use-json-for-advanced-querying-and-filtering.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/110_use-json-for-advanced-querying-and-filtering.md deleted file mode 100644 index e0c009a..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/020_Collection-resources/110_use-json-for-advanced-querying-and-filtering.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -type: MUST -id: R100041 ---- - -# use JSON for advanced querying and filtering - -If simple query parameters are too limiting for your complex use cases, introduce a separate `POST` endpoint, which accepts a query language as JSON. diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/000_index.md deleted file mode 100644 index b6b191f..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/000_index.md +++ /dev/null @@ -1,6 +0,0 @@ -# Naming conventions - -When resources are well-named, an API is intuitive and easy to use. -If resources are poorly named, the same API can feel difficult to use and understand. -Having a strong and consistent strategy for naming REST resources results in an easy-to-understand API that developers enjoy working with. -To make our API as easy to use as possible in this section we define our URI naming conventions. diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/010_must-avoid-actions-as-resource-names.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/010_must-avoid-actions-as-resource-names.md deleted file mode 100644 index 6f919e1..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/010_must-avoid-actions-as-resource-names.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -type: MUST -id: R000015 ---- - -# avoid actions as resource names - -REST is all about resources. -Therefore, we look at the domain entities involved in web service interaction, and try to model our API around them, using the standard HTTP methods as operational indicators. - -DO - -- `POST /orders/{orderId}` -- `DELETE /articles/{articleNumber}` -- `POST /articles/{articleNumber}/lock` - -DON'T - -- `POST /orders/create-order` -- `POST /articles/{articleNumber}/delete` -- `POST /artcles/lock-article/{articleNumber}` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/020_must-use-nouns-to-represent-resources.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/020_must-use-nouns-to-represent-resources.md deleted file mode 100644 index 9f2a487..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/020_must-use-nouns-to-represent-resources.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -type: MUST -id: R000016 ---- - -# use nouns to represent resources - -The API describes resources, so the only place where actions should appear is in the HTTP methods. -Keep URLs free of verbs and use only nouns. - -DO - -`/orders/{orderId}/processes/cancelations/{cancelationProcessId}` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/030_must-use-lowercase-letters-in-uris.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/030_must-use-lowercase-letters-in-uris.md deleted file mode 100644 index 7adad93..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/030_must-use-lowercase-letters-in-uris.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -type: MUST -id: R000017 ---- - -# use lowercase letters in URIs - -We consistently use lowercase letters in URI paths. - -DO - - - -DON'T - - diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/040_must-follow-a-logical-order.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/040_must-follow-a-logical-order.md deleted file mode 100644 index 14933d2..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/040_must-follow-a-logical-order.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -type: MUST -id: R000018 ---- - -# follow a logical order - -```plaintext -/customers/{userId}/addresses -/customers/{userId}/addresses/{addressId} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/050_must-use-forward-slash-to-indicate-hierarchical-relationships.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/050_must-use-forward-slash-to-indicate-hierarchical-relationships.md deleted file mode 100644 index db8099e..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/050_must-use-forward-slash-to-indicate-hierarchical-relationships.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -type: MUST -id: R000019 ---- - -# use forward slash (/) to indicate hierarchical relationships - -Use the forward slash (/) in the path portion of the URI to indicate a hierarchical relationship between resources. - -```plaintext -/customers/{userId} -/customers/{userId}/addresses -/customers/{userId}/addresses/{addressId} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/060_must-not-end-uri-with-a-trailing-slash.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/060_must-not-end-uri-with-a-trailing-slash.md deleted file mode 100644 index c5d5ad5..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/060_must-not-end-uri-with-a-trailing-slash.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -type: MUST NOT -id: R000020 ---- - -# end URIs with a trailing slash (/) - -As the last character in a URI's path does not add semantic value and may cause confusion, a URI must not end with a trailing slash (/). - -DO - -`/customers/{userId}/addresses/{addressId}` - -DON'T - -`/customers/{userId}/addresses/{addressId}/` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/070_must-use-camelcase-for-query-parameters.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/070_must-use-camelcase-for-query-parameters.md deleted file mode 100644 index 50546b3..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/070_must-use-camelcase-for-query-parameters.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -type: MUST -id: R000022 ---- - -# use camelCase for query parameters - -Use CamelCase to delimit combined words in query parameters. - -DO - -`productId`, `articleNumber`, `loginId`, `lId` etc. - -DON'T - -`product_id`, `Articlenumber`, `login-id`, `LID` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/080_must-support-lists-for-multiple-values-of-the-same-parameter.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/080_must-support-lists-for-multiple-values-of-the-same-parameter.md deleted file mode 100644 index f58b0ce..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/080_must-support-lists-for-multiple-values-of-the-same-parameter.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -type: MUST -id: R000062 ---- - -# support lists for multiple values of the same query parameter - -If multiple values need to be supported, they should be provided as a comma-separated list (e.g. `key=value1,value2`). - -Must not promote usage of multiple occurrence of the same parameter in the query string (e.g. `key=value1&key=value2`), prefer lists instead. diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/090_must-use-kebabcase-for-uris.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/090_must-use-kebabcase-for-uris.md deleted file mode 100644 index efe4050..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/090_must-use-kebabcase-for-uris.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -type: MUST -id: R000023 -reviewType: automatic ---- - -# use kebab-case for URIs - -When crafting a URI, we use a hyphen to delimit combined words (kebab-case). - -This is what a well-formed kebab-case URI looks like: - -`https://api.otto.de/carts/shipping-address` diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/100_must-use-url-friendly-resource-identifiers.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/100_must-use-url-friendly-resource-identifiers.md deleted file mode 100644 index 5b6dfc9..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/100_must-use-url-friendly-resource-identifiers.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -type: MUST -id: R000024 ---- - -# use URL-friendly resource identifiers - -To simplify encoding of resource IDs in URLs, their representation must only consist of ASCII strings. - -USE - -- letters [a-zA-Z] -- numbers [0-9] -- underscore \_ -- minus - -- colon : -- period . -- and - on rare occasions - slash / - -DON'T USE (among others) - -- umlauts äöü -- accents àèĉ -- eszett ß diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/110_must-stick-to-conventional-query-parameters.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/110_must-stick-to-conventional-query-parameters.md deleted file mode 100644 index 41f5207..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/110_must-stick-to-conventional-query-parameters.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -type: MUST -id: R000049 ---- - -# stick to conventional query parameters - -To provide clients with a consistent API, the following query parameters must be used instead of introducing custom parameters for the same functionality. - -## Paging - -This rule applies to public APIs. For private APIs it should be followed. - -| name | description | values | example | -| :--------- | :--------------------------------- | :----- | :-------------- | -| `pageSize` | Number of elements in the response | `1..` | `?pageSize=10` | -| `page` | Page number (0-indexed) | `0..` | `?page=2` | -| `after` | Results after the cursor position | \* | `?after=e2e3c` | -| `before` | Results before the cursor position | \* | `?before=129fa` | - - -## Sorting - -| name | description | values | example | -| :----- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------- | :---------------------- | -| `sort` | Property to sort by with optional ordering. Can be provided multiple times to sort by multiple properties. Naming should correspond to JSON field names with dot-navigation if necessary (e.g. `price.grossValue`). | `[:(asc\|desc)]` | `?sort=price:desc,name` | - -## Querying - -| name | description | values | example | -| :--- | :---------------- | :----- | :--------- | -| `q` | Simple text query | \* | `?q=shoes` | - -Introduce [your own descriptive query parameters for querying](R100031). - -If more advanced queries are necessary, make them available via [separate endpoints that accept queries as JSON payloads](R100041). - -## Filtering - -Depending on your use case and payload size, you can significantly reduce network bandwidth need by supporting filtering of returned entity fields. - -| name | description | values | example | -| :------- | :------------------------------------------ | :----- | :------------------------------ | -| `fields` | Selection of fields that should be returned | \* | `?fields=name,friends(id,name)` | - -See also [Filtering of fields using common query parameter](R004070) - -## Embedding - -| name | description | values | example | -| :------ | :---------------------------------------- | :----- | :----------------------------- | -| `embed` | Selection of link-relation types to embed | \* | `?embed=(item,item(o:images))` | - -Examples: - -- Do not embed anything: `?embed=()` -- Embed products into the response: `?embed=(o:product)` -- Embed all products and for every product also embed its variations: `?embed=(o:product, o:product(o:variation))` - diff --git a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/120_should-not-use-external-identifier-as-primary-resource-identifier.md b/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/120_should-not-use-external-identifier-as-primary-resource-identifier.md deleted file mode 100644 index c7aa816..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/030_Resources/030_Naming-conventions/120_should-not-use-external-identifier-as-primary-resource-identifier.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -type: SHOULD NOT -id: R100077 ---- - -# use external identifiers as primary resource identifiers - -When you create an API endpoint that requires a resource identifier, you SHOULD NOT use an external identifier as resource identifier. Example: You're about to implement `some-resource/{external-id}`, assuming that `some-resource` is your resource and `external-id` is an ID that is not under your control - you'd better not do that. - -Use one of the following options for your implementation instead: - -1. Use your own unique identifier representing the external identifier, e.g. `some-resource/{your-unique-id}`. -2. Use a templated hypermedia link, such as `o:templated-link`. -3. Use querying capabilities, e.g. `/some-resource?external-id-name={external-id}`. - - -This is why using an external identifier as primary resource identifier is not recommended: - -- The API will often respond with a 404 status for consumer requests with existing identifiers, causing issues for error monitoring. -- 404 errors should be reserved for rare cases, where an API forgets to notify a consumer about a resource being deleted and the consumer accesses this (now) stale link. -- Business need might change the relation. diff --git a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/040_Errors/000_index.md deleted file mode 100644 index d50802f..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/000_index.md +++ /dev/null @@ -1,9 +0,0 @@ -# Errors - -HTTP status codes are the most obvious choice for error communication, but they have a limited expressiveness. -Many status codes are too generic to explain the specific type of an error. -Most importantly, without contextual details, they are not particularly meaningful and user-friendly. - -Different frameworks provide their own methods for error responses. -Particularly in microservice architectures with different programming languages and frameworks in use, this is not optimal. -An API must always report the same error message scheme. diff --git a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/000_index.md deleted file mode 100644 index face61c..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/000_index.md +++ /dev/null @@ -1 +0,0 @@ -# Error handling diff --git a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/010_must-use-problem-json-as-error-response-format.md b/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/010_must-use-problem-json-as-error-response-format.md deleted file mode 100644 index d4dc819..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/010_must-use-problem-json-as-error-response-format.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -type: MUST -id: R000034 ---- - -# use `problem+json` as error response format - -We decided to adopt "Problem Details for HTTP APIs" as described in [RFC 7807](https://tools.ietf.org/html/rfc7807). -In case of an error, all REST operations must return an error response in this well-defined format along with the appropriate media type `application/problem+json`. This error response enhances the correctly used [HTTP status code](R000012) with contextual information. - -Example response: - -```http -HTTP/1.1 403 Forbidden -Content-Type: application/problem+json - -{ - "type": "about:blank", - "title": "Forbidden", - "status": 403, - "detail": "For data protection reasons, you are not allowed to view account details of others.", - "instance": "/account/12345/" -} -``` - -## Info -Always respond with the corresponding media type `application/problem+json` regardless of the given `accept` header. - -The [`type`](https://www.rfc-editor.org/rfc/rfc7807#section-3.1) of the problem object should be used to identify the problem type globally. -The URI does not need to be resolvable. If it is resolvable, it should contain a human-readable description of the problem type. - -Responses should [use existing error types](R000037) if possible to keep error churn as low as possible. - -Response properties in detail: - -| property | description | mandatory | -| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | -| `type` | Identifies the type of the problem. If it is a resolvable URL, the resolved content should contain a human-readable description of the problem type. If the problem type has no additional semantics beyond the HTTP status code, the URI `about:blank` can be used. | ✔ | -| `title` | Title should roughly contain and describe the problem. However, it should be static and not include a detailed error description, e.g., do not list the invalid values. If the type is `about:blank`, the reason phrase of the status should be used as title. | ✔ | -| `status` | Represents the corresponding [HTTP Status Code](R000012). | ✔ | -| `detail` | Should contain further details about the error. The RFC specifies that this field should not contain debugging information. Instead, it may contain details about the exact problem and how to solve it. It should not be parsed for further information. | ✗ | -| `instance` | It is possible to specify the instance of the service that has the problem or the relative URI that was called. | ✗ | - -## Important -In contrast to the RFC the properties `type`, `title`, and `status` are mandatory. diff --git a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/020_should-use-existing-problem-types.md b/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/020_should-use-existing-problem-types.md deleted file mode 100644 index 1e12b4b..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/020_should-use-existing-problem-types.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -type: SHOULD -id: R000037 ---- - -# use existing problem types - -In addition to the [predefined types](https://www.rfc-editor.org/rfc/rfc7807#section-4.2) in RFC7807, we have defined -the problem type [https://api.otto.de/portal/problems/validation-failed](@guidelines/R000038). - -We encourage API designers to reuse existing problem types instead of creating completely new or slightly modified ones. - -If none of the existing error types match the semantics of the problem, [defining a new problem type](@guidelines/R000040) is a feasible option. diff --git a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/030_must-use-extension-for-input-validation-errors.md b/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/030_must-use-extension-for-input-validation-errors.md deleted file mode 100644 index edc22ca..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/030_must-use-extension-for-input-validation-errors.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -type: MUST -id: R000038 ---- - -# use `problem+json` extension for input validation errors - -Validation checks can be performed on the request body, e.g. on form input values or business objects to be stored, as well as on path and query parameters. The `validation-failed` type should be used for all sorts of validation errors. All validation errors for one request should be combined into a self-sufficient error response that contains detailed messages for each failed check. - -If an input validation error occurs, we expect a `400 Bad Request` response. - -The problem `type` is defined as .
-The `title` should be _"Your request cannot be validated."_.
-The `status` code is always `400`. - -This results in the following structure: - -```json -{ - "type": "https://api.otto.de/portal/problems/validation-failed", - "title": "Your request cannot be validated.", - "status": 400, - "validationErrors": [ - { - "in": "query", - "path": "paymentType", - "invalidValue": "CHECK", - "details": [ - { - "key": "serviceX.payment.unknownValue", - "message": "The 'CHECK' value is not a known value for the 'paymentType' query parameter." - } - ] - } - ] -} -``` - -The added `validationErrors` property should contain detailed information about all validation errors that occurred during request validation. -Clients can parse the details section and handle the errors accordingly, e.g. display messages in the corresponding input form, remove items from the underlying collection, or request another user action. - -For each invalid property of the request body, path or query parameter, the API must respond with a dedicated validation error object. - -The following table shows the available properties: - -| property | description | mandatory | -| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | -| `in` | Shows the location of the validated object or attribute. Allowed values:
  • path - URL path, e.g. `my-path-param` in `myEndpoint/{my-path-param}/detailResource`.
  • query - query parameter, e.g. `pageSize` for pagination.
  • header - header parameter, e.g. for custom header.
  • body - if the validated element is part of the request body.
| ✔ | -| `path` | Depending on the "in" property, the path can have a different meaning:
  • path - The name of the invalid path parameter.
  • query - The name of the invalid query parameter.
  • header - The name of the invalid header.
  • body- A [JSONPath](https://goessner.net/articles/JsonPath/) that points to the invalid property.
| | -| `invalidValue` | Optional string representation of the invalid value that caused the validation error, e.g. a single word in a text property, which failed the check, etc. A missing `invalidValue` may express that no value or a null value has been provided in the request. | | -| `details` | Array of objects that hold at least one detail message for the given parameter or request body element. | ✔ | -| `details.key` | Mandatory error message key, which can be used to map the actual UI error message, e.g. in case of interationalization. The suggested format for strings is _service.object.errorKey_, e.g. _checkout.variation.alreadyExists_.
For fixed values, please [format enumerations in UPPER_SNAKE_CASE](@guidelines/R004090) | ✔ | -| `details.message` | Optional validation message describing the error in detail. Due to the `key` the message is optional, but still recommended for comprehensive stack tracing and logging. | - -We aim at consistent and informative validation messages. -We don't want nondescript validation messages. - -` `{label="danger"} Invalid -` `{label="warning"} "Not a valid US phone number" -` `{label="success"} "Not a valid 10-digit US phone number (must not include spaces or special characters)." - -The JSON response looks as follows (isolated from the problem details): - -```json -{ - "validationErrors": [ - { - "in": "[path|query|header|body]", - "path": "$.json.path.to.error.field", - "invalidValue": "Optional invalid client input as a string.", - "details": [ - { - "key": "machine.readable.key1", - "message": "First human-readable error message." - }, - { - "key": "machine.readable.key2", - "message": "Another human-readable error message." - } - ] - } - ] -} -``` - -Here's a comprehensive example (creating a fictional new partner): - -Functional API restrictions: - -- The `name` property must contain between 3 and 20 characters. -- The `name` property must not contain whitespace. -- The `bankAccount` items need an `iban` property. -- The new partner has to pass the credit check. - -Request payload: - -```json -{ - "name": "A-TOO-LONG-RETAILER-NAME WITH-WHITESPACE", - "bankAccounts": [ - { - "ownerName": "Otto" - } - ] -} -``` - -Corresponding error response: - -```json -{ - "type": "https://api.otto.de/portal/problems/validation-failed", - "title": "Your request cannot be validated.", - "status": 400, - "validationErrors": [ - { - "in": "body", - "path": "$.partner.name", - "invalidValue": "A-TOO-LONG-RETAILER-NAME WITH-WHITESPACE", - "details": [ - { - "key": "serviceX.partner.stringTooLong", - "message": "Name must have between 3 and 20 characters." - }, - { - "key": "serviceX.partner.noWhitespace", - "message": "Name must not contain whitespace." - } - ] - }, - { - "in": "body", - "path": "$.partner.bankAccounts[0].iban", - "details": [ - { - "key": "serviceX.partner.valueMissing", - "message": "IBAN must not be empty." - } - ] - }, - { - "in": "body", - "details": [ - { - "key": "serviceX.partner.creditCheckFailed", - "message": "Credit check was not successful." - } - ] - } - ] -} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/040_add-custom-extensions-by-defining-a-problem-type.md b/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/040_add-custom-extensions-by-defining-a-problem-type.md deleted file mode 100644 index 8ac4a08..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/040_Errors/010_Error-handling/040_add-custom-extensions-by-defining-a-problem-type.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -type: MAY -id: R000040 ---- - -# add custom extensions by defining a problem `type` - -As described in [section 3.2](https://www.rfc-editor.org/rfc/rfc7807#section-3.2) of [RFC 7807](https://www.rfc-editor.org/rfc/rfc7807) _problem `type` definitions may extend the problem details object with additional members_. -Thus, API providers need to define a specific problem `type` if they want to add additional non-standard properties to a problem+json response. - -In general, clients must ignore any extension they do not recognize. -This allows problem types to evolve and include additional information in the future. - -Before defining a new problem type, check if the type is really required and cannot be expressed just by using the HTTP status code. -For example communicating to the client that he is not allowed to place an order can easily be expressed by the generic HTTP status code [403 Forbidden](https://www.rfc-editor.org/rfc/rfc9110#name-403-forbidden). -If this is the case, just use the problem type [`about:blank`](https://www.rfc-editor.org/rfc/rfc7807#section-4.2) that signals that the problem is semantically identical to the meaning of the status code. - -Creating a new `type` always includes having a fixed human-readable `title` and a fixed `status` associated (see [https://www.rfc-editor.org/rfc/rfc7807#section-4](https://www.rfc-editor.org/rfc/rfc7807#section-4)). - -The URI encoded in `type` must be treated as an identifier that should not change. While encouraged, it does not need to be resolvable. -The `type` URI should be in the same URL namespace as the APIs endpoints. If all API endpoints are located under `https://api.otto.de/payment/` the custom `type` URLs should als be located under the same context path (e.g., `https://api.otto.de/payment/problems/credit-too-low`). -If possible, API providers should provide a `type` URL that resolves to a human-readable documentation (e.g., HTML) of the problem type. - -Example: - -A new context-specific type `https://api.otto.de/payment/problems/credit-too-low` is introduced. It adds the properties `maxCredit` and `requiredCredit`. - -```json -{ - "type": "https://api.otto.de/payment/problems/credit-too-low", - "title": "Credit too low", - "status": 422, - "detail": "The required credit \"40 €\" exceeds the maximal credit for the customer \"20 €\".", - "requiredCredit": 4000, - "maxCredit": 2000 -} -``` - -Example documentation: -Problem type: - -Title: Credit too low - -Status: 422 - -Description: This problem indicates that the credit associated with the customer account is insufficient to perform the operation of the request. The maximal credit will be communicated in the `maxCredit` property. - -Additional properties: - -- `maxCredit`: The maximal credit for the customer in euro cents. May not be present due to access restrictions. -- `requiredCredit`: The required credit for the operation in euro cents. Always present. - -Example: - -```json -{ - "type": "https://api.otto.de/payment/problems/credit-too-low", - "title": "Credit too low", - "status": 422, - "detail": "The required credit \"40 €\" exceeds the maximal credit for the customer \"20 €\".", - "requiredCredit": 4000, - "maxCredit": 2000 -} -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/000_index.md deleted file mode 100644 index 55167cf..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/000_index.md +++ /dev/null @@ -1,6 +0,0 @@ -# Compatibility - -This section contains REST API specific rules to maintain compatibility. - -This section contains REST API-specific rules to maintain compatibility. -Also consider the rules defined in the [general guidelines for compatibility](../../020_GENERAL-GUIDELINES/030_Compatibility/000_index.md). diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/000_index.md deleted file mode 100644 index 69f67e2..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/000_index.md +++ /dev/null @@ -1,5 +0,0 @@ -# Client behavior - -Clients must be tolerant to changes of REST APIs. The rules in this section define how clients should behave to ease API evolution. - -This section contains REST API-specific additions to the general rule [MUST prepare consumers to accept compatible API extensions](@guidelines/R000029). diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/010_must-send-unknown-fields-in-put-requests.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/010_must-send-unknown-fields-in-put-requests.md deleted file mode 100644 index 066e905..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/010_must-send-unknown-fields-in-put-requests.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -type: MUST -id: R000079 -appliesTo: client ---- - -# send unknown fields in PUT requests - -To allow API evolution of services, clients must not break if providers add new properties to responses (see [MUST prepare consumers to accept compatible API extensions](@guidelines/R000029)). - -A client that needs to update a resource, first has to retrieve the current state of the resource using a GET request. The client may then perform the necessary modifications ignoring unknown properties. In the subsequent PUT request for updating the resource on the server, the client must send all properties (i.e. known and unknown properties) to the server. diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/020_must-accept-undocumented-status-codes.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/020_must-accept-undocumented-status-codes.md deleted file mode 100644 index 22bd769..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/020_must-accept-undocumented-status-codes.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -type: MUST -id: R000080 -appliesTo: client ---- - -# accept undocumented status codes - -Clients must be prepared to handle HTTP status codes not explicitly specified in endpoint definitions. - -Clients are not required to understand every status code returned, but they must at least understand the class of each status code (i.e. 1xx, 2xx, 3xx, 4xx, 5xx) as defined in [RFC 7231 Section 6](https://tools.ietf.org/html/rfc7231#section-6). Clients must treat an unrecognized status code equivalent to the x00 status code (i.e. 100, 200, 300, 400, 500) of its class. diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/030_must-follow-redirection.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/030_must-follow-redirection.md deleted file mode 100644 index 9e29046..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/010_Client-behavior/030_must-follow-redirection.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -type: MUST -id: R000081 -appliesTo: client ---- - -# follow redirection - -Clients must follow the redirect when the server returns the HTTP status code `HTTP 301 Moved Permanently`. This allows services to evolve without breaking compatibility. diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/000_index.md deleted file mode 100644 index 75407a3..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/000_index.md +++ /dev/null @@ -1,21 +0,0 @@ -# Versioning of incompatible changes - -OTTO API supports two versioning approaches for HTTP APIs: via [profiles](@guidelines/R000065) and via [URL path](@guidelines/R000031). Versioning via profiles is preferred. - -## Why profile versioning - -We cannot go with a single global version number for the entire OTTO REST API, as this would mean too much coordination overhead for our feature teams. -To implement versioning for REST APIs, we want to use industry standards wherever possible. Thus, we exclude solutions that violate existing standards or are based on draft standards that might change in an incompatible way. - -URL-based versioning links only to a specific version of a resource and creates a fixed dependency on a specific version. This conflicts with the use of hypermedia/HAL. Therefore, versioning must be done via profiles. -In addition, profiles also allow resource/sub-resource independent versioning. - -In cases where profile-based versioning is not possible or sufficient, URL-based versioning can be applied. - -During the initial discussion of versioning, several options have been [identified and evaluated (internal link)](https://github.com/otto-ec/ottoapi_guidelines/blob/main/content/references/REST/versioning.md). - -References: -- [Profiles in HAL+JSON](https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-08#page-8) -- [The 'profile' Link Relation Type (RFC 9606)](https://tools.ietf.org/html/rfc6906) -- [SHOULD use `Accept` and `Content-Type` headers with profile parameter](@guidelines/R000030) -- [MUST provide conventional hyperlinks](@guidelines/R100033) diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/010_must-use-profiles-for-public-rest-apis.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/010_must-use-profiles-for-public-rest-apis.md deleted file mode 100644 index edb3c64..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/010_must-use-profiles-for-public-rest-apis.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -type: MUST -id: R000065 ---- - -# use profiles for Public REST APIs - -[Public APIs](../../../010_CORE-PRINCIPLES/030_API-scope.md) have to be versioned with [profiles](../../020_Hypermedia/040_Profiles/000_index.md) and provide comprehensive profile documentation using custom `x-ottoapi` tags. - -```yml -openapi: 3.0.3 - -x-ottoapi: - profiles: - "{{service.profiles}}/checkout/delivery-methods+v1": - title: Delivery methods - description: Contains the delivery address type allowed for a specific checkout. - schema: - $ref: ./schemas.yml#/components/schemas/DeliveryMethodOptions - examples: - v1: - $ref: ./examples.yml#/components/examples/DeliveryMethodsResponseV1 - "{{service.profiles}}/checkout/delivery-methods+v2": - <<: *delivery-methods-v1 - description: | - Contains the delivery address type allowed for a specific checkout. Includes express delivery options. - schema: - $ref: ./schemas.yml#/components/schemas/DeliveryMethodOptionsV2 - examples: - v2: - $ref: ./examples.yml#/components/examples/DeliveryMethodsResponseV2 - -paths: [...] -``` diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/020_should-use-accept-and-content-type-headers-with-profile-parameter.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/020_should-use-accept-and-content-type-headers-with-profile-parameter.md deleted file mode 100644 index d309ea4..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/020_should-use-accept-and-content-type-headers-with-profile-parameter.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -type: SHOULD -id: R000030 ---- - -# use `Accept` and `Content-Type` headers with profile parameter - -Change your RESTful APIs in a compatible way and avoid generating additional API versions. -Multiple versions can significantly complicate understanding, testing, maintaining, evolving, operating and releasing our systems ([supplementary reading](http://martinfowler.com/articles/enterpriseREST.html)). - -If the modification of an API cannot be done in a compatible way, versioning should be implemented using the `Accept` and `Content-Type` header with `profile` parameter. - -If the client does not specify the required `profile` in the `Accept` header, the server may choose which version is returned. - -If the client does not specify the `Content-Type` header with `profile` parameter in a request with a body, the server may refuse the request with status code `400 Bad Request`. - -The server may decline invalid combinations of `Content-Type` and `Accept` headers with `406 Not Acceptable`. For endpoint methods featuring both a request and a response body (e.g. `POST`), only requests for the same profile version in request and response body (via `Content-Type` and `Accept` header) must be supported. - -References: -- [MUST use profiles for Public APIs](@guidelines/R000065) -- [MUST use resolvable profile URLs](@guidelines/R100066) -- [MUST provide OpenAPI spec for profiles](@guidelines/R100067) -- [RFC 7231, p. 59: 406 for unsupported versions](https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.6) diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/030_should-not-use-resource-versioned-path.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/030_should-not-use-resource-versioned-path.md deleted file mode 100644 index 979fb24..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/030_should-not-use-resource-versioned-path.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -type: SHOULD NOT -id: R000031 ---- - -# use resource versioned path - -Version numbers in URLs should not be used. -However, if the preferred versioning option is not possible, -a [resource versioned path (internal link)](https://github.com/otto-ec/ottoapi_guidelines/blob/main/content/references/REST/versioning.md#resource-versioned-paths) may be introduced, if absolutely required. diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/040_should-not-use-uri-versioning.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/040_should-not-use-uri-versioning.md deleted file mode 100644 index 94a38e1..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/020_Versioning/040_should-not-use-uri-versioning.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -type: SHOULD NOT -id: R000026 ---- - -# use URI versioning - -If you absolutely have to use a version identifier as part of your URL, do so by keeping it as a path segment relative to your resource. - -DO - -- `/users/{user-identifier}` -- `/users/v2/{user-identifier}` - -DON'T - -- `/users/{user-identifier}?version=2` -- `/v2/users/{user-identifier}` diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/000_index.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/000_index.md deleted file mode 100644 index 80920ea..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/000_index.md +++ /dev/null @@ -1,3 +0,0 @@ -# Deprecation of HTTP APIs - -HTTP APIs need to provide deprecation and sunset information _on the wire_. The following rules define this requirement in more detail. diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/010_must-monitor-usage-of-deprecated-api-scheduled-for-sunset.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/010_must-monitor-usage-of-deprecated-api-scheduled-for-sunset.md deleted file mode 100644 index 60cccea..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/010_must-monitor-usage-of-deprecated-api-scheduled-for-sunset.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -type: MUST -id: R000068 ---- - -# monitor usage of deprecated API scheduled for sunset - -API providers must monitor the usage of the sunset API, API version, or API feature in order to observe migration progress and avoid uncontrolled breaking effects on clients still using the API. diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/020_should-add-deprecation-and-sunset-header-to-responses.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/020_should-add-deprecation-and-sunset-header-to-responses.md deleted file mode 100644 index 224d7b3..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/020_should-add-deprecation-and-sunset-header-to-responses.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -type: SHOULD -id: R000069 ---- - -# add `Deprecation` and `Sunset` header to responses - -During the deprecation phase, the API provider should add a `Deprecation` header (see [draft: RFC Deprecation HTTP Header](https://tools.ietf.org/html/draft-dalal-deprecation-header)) and - if also planned - a `Sunset` header (see [RFC 8594](https://tools.ietf.org/html/rfc8594#section-3)) to each response affected by a deprecated element (see [MUST reflect deprecation in API specifications](@guidelines/R000067)). - -The `Deprecation` header can either be set to `true` when a feature is disabled, or it can carry a deprecation timestamp at which a replacement is made available and consumers are no longer allowed to use the feature (see [MUST NOT start using deprecated APIs](@guidelines/R000071)). -The optional `Sunset` timestamp indicates when consumers have to stop using a feature at the latest. -The sunset timestamp should always offer an appropriate time interval for switching to a replacement feature. - -Example: - -```http -Deprecation: Sun, 31 Dec 2024 23:59:59 GMT -Sunset: Sun, 31 Dec 2025 23:59:59 GMT -``` - -If multiple elements are deprecated, the `Deprecation` and `Sunset` headers are expected to be set to the earliest timestamp to reflect the shortest interval consumers are expected to get active. - -Adding the `Deprecation` and `Sunset` header to the response is not sufficient to gain client consent to shut down an API or feature. diff --git a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/030_should-add-monitoring-for-deprecation-and-sunset-header.md b/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/030_should-add-monitoring-for-deprecation-and-sunset-header.md deleted file mode 100644 index 23eda12..0000000 --- a/03_api_guidelines/030_REST-GUIDELINES/050_Compatibility/040_Deprecation/030_should-add-monitoring-for-deprecation-and-sunset-header.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -type: SHOULD -id: R000070 -appliesTo: client ---- - -# add monitoring for `Deprecation` and `Sunset` header - -Consumers should monitor the `Deprecation` and `Sunset` headers in HTTP responses to get information about future sunset of APIs and API features (see [SHOULD add `Deprecation` and `Sunset` header to responses](@guidelines/R000069)). -We recommend that API providers build alerts on this monitoring information to ensure alignment with API consumers on the required migration task. diff --git a/04_products_api/API_error_codes.md b/03_products_api/API_error_codes.md similarity index 100% rename from 04_products_api/API_error_codes.md rename to 03_products_api/API_error_codes.md diff --git a/04_products_api/README.md b/03_products_api/README.md similarity index 95% rename from 04_products_api/README.md rename to 03_products_api/README.md index 0f1520b..8bf1cf6 100644 --- a/04_products_api/README.md +++ b/03_products_api/README.md @@ -1,4 +1,4 @@ -# OTTO Retail-API specifications +# OTTO Retail-API - products API specifications At the moment our API is in a beta version. This means that - although the API is already in a very advanced and stable state - there is still the possibility that different elements of the API might change (path, parameters, return objects etc.) as we are learning from the feedback of our early adaptors. We welcome explicitly early adaptors at this point. @@ -12,9 +12,12 @@ Please note that articles where you need to specify material composition such as ### Change Log -| *Date* | *Classification* | *Description* | -| 2023-06-02 | Documentation | Intial Version of documentation | -| 2023-06-02 | New Version | Initial Version of the api has been released. | + +| Date | Classification | Description | +| ------------- | ----------------- | --------------------------------------------- | +| 2023-06-02 | Documentation | Initial Version of documentation | +| 2023-06-02 | New Version | Initial Version of the api has been released. | + ## Implementing the products API @@ -36,7 +39,7 @@ The API as well as the metadata (brands, category groups, ..) that you can retri ### Authentication -The information about the authentication can be found [here](../01_getting-started/02_authentication.md) +The information about the authentication can be found [here](../01_getting-started/01_authentication.md) ## Preparation of product data transfer diff --git a/04_products_api/products-api.yml b/03_products_api/products-api.yml similarity index 100% rename from 04_products_api/products-api.yml rename to 03_products_api/products-api.yml diff --git a/README.md b/README.md index 6dd061b..5e5acb3 100644 --- a/README.md +++ b/README.md @@ -16,13 +16,17 @@ Before you start the implementation, please read the [Getting Started guide](01_ ### Implementing the API -To implement the API we offer a sandbox environment which you can use to develop and test the API access. As a first step, please request a client for the sandbox environment. Once you have successfully submitted your data in the sandbox environment please request the client for production use in order to submit your data to OTTO. +To implement the API we offer a sandbox environment which you can use to develop and test the API access. +As a first step, please request a client for the sandbox environment. +Once you have successfully submitted your data in the sandbox environment please request the client for production use in order to submit your data to OTTO. -To implement the API you find all the necessary information in the detailed API Guide: [About the API](04_products_api) +#### Products API + +To implement the Retail-API products API you find all the necessary information in the detailed API Guide: [Products API](03_products_api) ### Further information -Further general information can be found in the [OTTO API Guidelines](03_api_guidelines/000_index.md) and [About the API](02_about-the-api). +Further general information can be found in [about the API](02_about-the-api) and the [OTTO API Guidelines](https://github.com/otto-de/api-guidelines/tree/main). ### This repository This repository contains a collection of documents and related materials for the implementation of the OTTO Retail-API.