diff --git a/assets/scss/_rest-api-reference.scss b/assets/scss/_rest-api-reference.scss new file mode 100644 index 000000000..e1035e346 --- /dev/null +++ b/assets/scss/_rest-api-reference.scss @@ -0,0 +1,910 @@ +$method-get: #3f9abc; +$method-post: #3aae97; +$method-put: #1eaaaf; +$method-patch: #36bea1; +$method-delete: #dd4a54; +$method-options: #607680; +$method-head: #7d8790; + +@mixin rest-api-surface($background: rgba($dark, 0.82), $border: rgba($white, 0.08)) { + background: $background; + border: 1px solid $border; + border-radius: 1.1rem; + box-shadow: 0 20px 42px rgba($black, 0.16); +} + +@mixin method-badge($background) { + background: $background; + color: $white; +} + +.rest-api-reference-page { + .td-content { + max-width: none; + } + + .rest-api-content-shell { + > .rest-api-page, + > .rest-api-overview, + > .rest-api-controls { + max-width: none; + } + } + + .rest-api-page { + display: flex; + flex-direction: column; + gap: 1.5rem; + margin: 2rem 0 1rem; + } + + .rest-api-overview, + .rest-api-controls, + .rest-api-sidebar, + .rest-api-operation { + @include rest-api-surface(); + } + + .rest-api-overview, + .rest-api-controls, + .rest-api-sidebar, + .rest-api-operation { + padding: 1.4rem; + } + + .rest-api-overview__eyebrow, + .rest-api-section-heading__eyebrow, + .rest-api-controls__label, + .rest-api-nav-group__title { + margin: 0 0 0.45rem; + font-size: 0.78rem; + font-weight: 700; + letter-spacing: 0.09em; + text-transform: uppercase; + color: $primary; + } + + .rest-api-overview__summary, + .rest-api-section-heading__summary, + .rest-api-results__text, + .rest-api-nav-group__description, + .rest-api-operation__summary, + .rest-api-prose, + .rest-api-response__summary { + color: $casper; + } + + .rest-api-overview__summary { + margin: 0; + max-width: 72ch; + line-height: 1.7; + } + + .rest-api-overview__stats, + .rest-api-nav-list, + .rest-api-meta { + list-style: none; + margin: 0; + padding: 0; + } + + .rest-api-overview__stats { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); + gap: 0.85rem; + margin-top: 1rem; + } + + .rest-api-overview__stats li { + padding: 0.95rem 1rem; + border-radius: 0.95rem; + background: rgba($white, 0.03); + border: 1px solid rgba($white, 0.08); + display: flex; + flex-direction: column; + gap: 0.25rem; + } + + .rest-api-overview__stats strong { + font-size: 1.02rem; + color: $white; + } + + .rest-api-overview__stats span { + font-size: 0.92rem; + } + + .rest-api-overview__stats a { + color: $primary; + text-decoration: underline; + text-underline-offset: 0.15em; + } + + .rest-api-controls { + display: grid; + gap: 1.1rem; + } + + .rest-api-search-label { + display: block; + margin-bottom: 0.45rem; + font-size: 0.9rem; + font-weight: 600; + color: $white; + } + + .rest-api-search { + width: 100%; + border: 1px solid rgba($white, 0.12); + border-radius: 0.85rem; + background: rgba($black, 0.24); + color: $white; + font: inherit; + padding: 0.9rem 1rem; + transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease; + } + + .rest-api-search::placeholder { + color: rgba($casper, 0.85); + } + + .rest-api-search:focus { + outline: none; + border-color: rgba($white, 0.2); + box-shadow: 0 0 0 3px rgba($white, 0.08); + background: rgba($black, 0.34); + } + + .rest-api-category-bar { + display: flex; + flex-wrap: wrap; + gap: 0.7rem; + } + + .rest-api-category-button { + display: inline-flex; + align-items: center; + gap: 0.55rem; + padding: 0.55rem 0.85rem; + border-radius: 999px; + border: 1px solid rgba($primary, 0.24); + background: rgba($white, 0.02); + color: $casper; + font: inherit; + font-size: 0.92rem; + cursor: pointer; + transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease, transform 0.2s ease; + } + + .rest-api-category-button:hover, + .rest-api-category-button:focus-visible { + outline: none; + border-color: rgba($secondary, 0.9); + background: rgba($primary, 0.12); + color: $white; + } + + .rest-api-category-button.is-active { + background: rgba($white, 0.08); + border-color: rgba($white, 0.14); + color: $white; + } + + .rest-api-category-button__count, + .rest-api-nav-group__count { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 1.9rem; + padding: 0.18rem 0.5rem; + border-radius: 999px; + background: rgba($black, 0.28); + border: 1px solid rgba($primary, 0.25); + font-size: 0.8rem; + color: $white; + } + + .rest-api-results__text { + margin: 0; + font-size: 0.95rem; + line-height: 1.6; + } + + .rest-api-layout { + display: grid; + grid-template-columns: minmax(0, 1fr); + gap: 1.5rem; + align-items: start; + } + + .rest-api-sidebar { + position: static; + align-self: stretch; + max-height: none; + overflow: visible; + } + + .rest-api-sidebar__inner { + display: flex; + flex-direction: column; + min-height: auto; + height: auto; + } + + .rest-api-nav-toolbar { + display: flex; + justify-content: flex-end; + margin-bottom: 1.25rem; + } + + .rest-api-nav-control { + display: inline-flex; + align-items: center; + gap: 0.55rem; + padding: 0.65rem 1rem; + border-radius: 999px; + border: 1px solid rgba($white, 0.12); + background: rgba($white, 0.04); + color: $white; + cursor: pointer; + transition: border-color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease; + } + + .rest-api-nav-control:hover, + .rest-api-nav-control:focus-visible { + outline: none; + border-color: rgba($white, 0.22); + background: rgba($white, 0.07); + box-shadow: 0 0 0 3px rgba($white, 0.08); + } + + .rest-api-nav-control:disabled { + opacity: 0.55; + cursor: default; + box-shadow: none; + } + + .rest-api-nav-control__icon { + display: inline-flex; + flex-direction: column; + gap: 0.2rem; + } + + .rest-api-nav-control__icon span { + display: block; + width: 0.8rem; + height: 2px; + border-radius: 999px; + background: currentColor; + } + + .rest-api-nav-control[data-toggle-mode="expand"] .rest-api-nav-control__icon span:last-child { + width: 0.5rem; + } + + .rest-api-nav-control__text { + font-size: 0.95rem; + font-weight: 600; + } + + .rest-api-nav { + display: flex; + flex-direction: column; + gap: 1.6rem; + min-height: auto; + overflow: visible; + padding-right: 0; + } + + .rest-api-nav-group { + display: flex; + flex-direction: column; + gap: 0.75rem; + } + + .rest-api-nav-group__heading { + margin: 0; + padding: 0 0.2rem; + font-size: 0.94rem; + font-weight: 500; + letter-spacing: 0.08em; + text-transform: uppercase; + color: rgba($white, 0.68); + } + + .rest-api-nav-group__items { + display: flex; + flex-direction: column; + gap: 0.25rem; + padding: 0.45rem 1rem 0.55rem; + border-radius: 1.15rem; + border: 1px solid rgba($white, 0.06); + background: rgba($white, 0.02); + box-shadow: inset 0 1px 0 rgba($white, 0.03); + } + + .rest-api-nav-subgroup { + display: flex; + flex-direction: column; + border-top: 0; + } + + .rest-api-nav-subgroup + .rest-api-nav-subgroup { + margin-top: 0.15rem; + } + + .rest-api-nav-subgroup__toggle { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + width: 100%; + padding: 0.95rem 0.35rem; + border-radius: 0.95rem; + border: 0; + background: transparent; + color: $white; + text-align: left; + cursor: pointer; + transition: color 0.2s ease; + } + + .rest-api-nav-subgroup__toggle:hover, + .rest-api-nav-subgroup__toggle:focus-visible { + outline: none; + color: $white; + } + + .rest-api-nav-subgroup.is-open .rest-api-nav-subgroup__toggle { + background: transparent; + } + + .rest-api-nav-subgroup__title { + min-width: 0; + font-size: 1.05rem; + font-weight: 500; + letter-spacing: 0.01em; + color: inherit; + } + + .rest-api-nav-subgroup__toggle-meta { + display: inline-flex; + align-items: center; + gap: 0.9rem; + flex: 0 0 auto; + } + + .rest-api-nav-subgroup__count { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 2.35rem; + padding: 0.3rem 0.7rem; + border-radius: 999px; + background: rgba($white, 0.08); + border: 1px solid rgba($white, 0.12); + font-size: 0.95rem; + font-weight: 600; + color: rgba($white, 0.92); + } + + .rest-api-nav-subgroup__chevron { + width: 0.78rem; + height: 0.78rem; + border-right: 2px solid $casper; + border-bottom: 2px solid $casper; + transform: rotate(-45deg); + transform-origin: center; + transition: transform 0.2s ease, border-color 0.2s ease; + } + + .rest-api-nav-subgroup.is-open .rest-api-nav-subgroup__chevron { + transform: rotate(45deg); + border-color: $white; + } + + .rest-api-nav-subgroup__panel { + display: flex; + flex-direction: column; + gap: 0.75rem; + padding: 0 0.35rem 1rem 1.1rem; + } + + .rest-api-nav-list { + display: flex; + flex-direction: column; + gap: 0.55rem; + } + + .rest-api-nav-list--endpoints { + padding-left: 1rem; + border-left: 1px solid rgba($white, 0.08); + } + + .rest-api-nav-item { + margin: 0; + } + + .rest-api-nav-link { + display: block; + border-radius: 1rem; + border: 1px solid rgba($primary, 0.18); + background: rgba($white, 0.02); + padding: 0.85rem; + transition: border-color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease; + } + + .rest-api-nav-link:hover { + text-decoration: none; + border-color: rgba($secondary, 0.7); + background: rgba($primary, 0.09); + box-shadow: 0 10px 30px rgba($black, 0.16); + } + + .rest-api-nav-link.is-active { + border-color: rgba($secondary, 0.85); + background: rgba($white, 0.05); + box-shadow: 0 14px 28px rgba($black, 0.18); + } + + .rest-api-nav-link__top { + display: flex; + align-items: flex-start; + gap: 0.75rem; + min-width: 0; + } + + .rest-api-nav-link__path, + .rest-api-operation__path, + .rest-api-try-item__url { + font-family: $font-family-monospace; + overflow-wrap: anywhere; + word-break: break-word; + } + + .rest-api-nav-link__path { + min-width: 0; + color: $white; + line-height: 1.5; + } + + .rest-api-nav-link__summary { + display: block; + margin-top: 0.55rem; + font-size: 0.88rem; + line-height: 1.5; + color: $casper; + } + + .rest-api-nav__empty { + margin: 0; + padding-top: 1rem; + border-top: 1px solid rgba($primary, 0.18); + font-size: 0.92rem; + color: $casper; + } + + .rest-api-content { + min-width: 0; + } + + .rest-api-page.is-enhanced .rest-api-operation { + display: none; + } + + .rest-api-page.is-enhanced .rest-api-operation.is-active { + display: block; + } + + .rest-api-operation__header { + display: flex; + flex-direction: column; + gap: 0.75rem; + } + + .rest-api-operation__labels { + display: flex; + flex-wrap: wrap; + gap: 0.6rem; + } + + .rest-api-operation__path { + margin: 0; + color: $white; + font-size: 1.75rem; + line-height: 1.25; + } + + .rest-api-operation__summary { + margin: 0; + font-size: 1.05rem; + font-weight: 600; + } + + .rest-api-prose, + .rest-api-response__summary { + line-height: 1.7; + } + + .rest-api-prose p, + .rest-api-response__summary p { + margin: 0; + } + + .rest-api-prose p + p, + .rest-api-response__summary p + p { + margin-top: 0.7rem; + } + + .rest-api-prose a, + .rest-api-response__summary a { + color: $primary; + text-decoration: underline; + text-underline-offset: 0.15em; + } + + .rest-api-meta { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); + gap: 0.85rem; + margin-top: 1rem; + } + + .rest-api-meta__item, + .rest-api-section-block, + .rest-api-media-block, + .rest-api-response, + .rest-api-variant, + .rest-api-try-item { + background: rgba($white, 0.03); + border: 1px solid rgba($white, 0.08); + border-radius: 1rem; + } + + .rest-api-meta__item { + padding: 1rem; + } + + .rest-api-meta__item dt { + margin: 0; + font-size: 0.8rem; + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; + color: $primary; + } + + .rest-api-meta__item dd { + margin: 0.4rem 0 0; + font-size: 0.96rem; + line-height: 1.6; + color: $white; + } + + .rest-api-section { + margin-top: 1.5rem; + padding-top: 1.5rem; + border-top: 1px solid rgba($white, 0.08); + } + + .rest-api-section > h3, + .rest-api-section-heading--responses h3, + .rest-api-section-heading--try h3 { + margin: 0; + color: $white; + font-size: 1.2rem; + } + + .rest-api-section-heading__summary { + margin: 0.5rem 0 0; + max-width: 62ch; + font-size: 0.95rem; + line-height: 1.65; + } + + .rest-api-section--responses { + margin-top: 1.9rem; + padding: 1.45rem; + border-radius: 1rem; + background: rgba($black, 0.18); + border: 1px solid rgba($white, 0.09); + box-shadow: inset 0 1px 0 rgba($white, 0.03); + } + + .rest-api-section--responses .rest-api-section-heading--responses { + margin-bottom: 1.2rem; + padding-bottom: 1.2rem; + border-bottom: 1px solid rgba($white, 0.07); + } + + .rest-api-section--try { + padding: 1.2rem; + border: 1px dashed rgba($white, 0.12); + border-radius: 1rem; + background: rgba($white, 0.03); + } + + .rest-api-section-block, + .rest-api-media-block, + .rest-api-response, + .rest-api-variant, + .rest-api-try-item { + padding: 1rem; + } + + .rest-api-section-block + .rest-api-section-block, + .rest-api-media-block + .rest-api-media-block, + .rest-api-response + .rest-api-response { + margin-top: 1.25rem; + } + + .rest-api-response { + background: rgba($white, 0.025); + box-shadow: inset 0 1px 0 rgba($white, 0.025); + } + + .rest-api-response--success { + border-left: 3px solid rgba($method-post, 0.95); + } + + .rest-api-response--info { + border-left: 3px solid rgba($method-put, 0.95); + } + + .rest-api-response--warning { + border-left: 3px solid rgba(#d8952d, 0.95); + } + + .rest-api-response--danger { + border-left: 3px solid rgba($method-delete, 0.95); + } + + .rest-api-section-block__title, + .rest-api-example__title, + .rest-api-variant__title, + .rest-api-try-item__label { + margin: 0 0 0.85rem; + font-size: 0.92rem; + font-weight: 700; + color: $white; + } + + .rest-api-variant-grid { + display: flex; + flex-direction: column; + gap: 1rem; + } + + .rest-api-media-block__header, + .rest-api-response__header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 0.8rem; + margin-bottom: 0.95rem; + } + + .rest-api-media-block__title { + margin: 0; + font-size: 1rem; + font-weight: 700; + color: $white; + } + + .rest-api-media-block__summary { + margin: 0.3rem 0 0; + font-size: 0.92rem; + color: $casper; + } + + .rest-api-example { + margin-top: 1rem; + } + + .rest-api-example pre, + .rest-api-operation pre { + margin: 0; + padding: 1rem; + border-radius: 0.95rem; + border: 1px solid rgba($white, 0.08); + background: rgba($black, 0.28); + overflow: auto; + } + + .rest-api-example code, + .rest-api-operation pre code { + display: block; + width: 100%; + background: transparent; + color: $white; + padding: 0; + white-space: pre-wrap; + overflow-wrap: anywhere; + } + + .rest-api-status, + .rest-api-chip, + .rest-api-method-badge { + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 999px; + white-space: nowrap; + font-weight: 700; + } + + .rest-api-status { + min-width: 3.2rem; + padding: 0.45rem 0.8rem; + font-size: 0.9rem; + background: rgba($white, 0.1); + color: $white; + } + + .rest-api-chip { + padding: 0.35rem 0.75rem; + border: 1px solid rgba($white, 0.1); + background: rgba($white, 0.03); + font-size: 0.82rem; + color: $white; + } + + .rest-api-chip--subtle { + color: $casper; + } + + .rest-api-method-badge { + min-width: 4.25rem; + padding: 0.38rem 0.72rem; + font-size: 0.8rem; + letter-spacing: 0.05em; + } + + .rest-api-method-badge--get { @include method-badge($method-get); } + .rest-api-method-badge--post { @include method-badge($method-post); } + .rest-api-method-badge--put { @include method-badge($method-put); } + .rest-api-method-badge--patch { @include method-badge($method-patch); } + .rest-api-method-badge--delete { @include method-badge($method-delete); } + .rest-api-method-badge--options { @include method-badge($method-options); } + .rest-api-method-badge--head { @include method-badge($method-head); } + + .rest-api-response--success .rest-api-status { @include method-badge($method-post); } + .rest-api-response--info .rest-api-status { @include method-badge($method-put); } + .rest-api-response--warning .rest-api-status { @include method-badge(#d8952d); } + .rest-api-response--danger .rest-api-status { @include method-badge($method-delete); } + + .rest-api-muted { + color: $casper; + font-size: 0.92rem; + } + + .rest-api-table-wrapper { + overflow-x: auto; + } + + .rest-api-table-wrapper > table { + display: table; + width: 100%; + min-width: 100%; + table-layout: fixed; + margin-bottom: 0; + } + + .rest-api-table-wrapper th, + .rest-api-table-wrapper td { + max-width: none; + vertical-align: top; + overflow-wrap: anywhere; + word-break: break-word; + } + + .rest-api-table-wrapper th:nth-child(1), + .rest-api-table-wrapper td:nth-child(1) { + width: 18%; + } + + .rest-api-table-wrapper th:nth-child(2), + .rest-api-table-wrapper td:nth-child(2) { + width: 16%; + } + + .rest-api-table-wrapper th:nth-child(3), + .rest-api-table-wrapper td:nth-child(3) { + width: 12%; + } + + .rest-api-table-wrapper th:nth-child(4), + .rest-api-table-wrapper td:nth-child(4) { + width: 54%; + } + + .rest-api-table-wrapper td p { + margin: 0; + } + + .rest-api-table-wrapper td p + p { + margin-top: 0.4rem; + } + + .rest-api-table-wrapper td code { + word-break: break-word; + } + + [hidden] { + display: none !important; + } + + @media (max-width: 800px) { + .rest-api-overview, + .rest-api-controls, + .rest-api-sidebar, + .rest-api-operation { + padding: 1.15rem; + } + + .rest-api-operation__path { + font-size: 1.4rem; + } + + .rest-api-media-block__header, + .rest-api-response__header, + .rest-api-nav-subgroup__toggle { + flex-direction: column; + align-items: flex-start; + } + + .rest-api-table-wrapper th:nth-child(1), + .rest-api-table-wrapper td:nth-child(1) { + width: 20%; + } + + .rest-api-table-wrapper th:nth-child(2), + .rest-api-table-wrapper td:nth-child(2) { + width: 18%; + } + + .rest-api-table-wrapper th:nth-child(3), + .rest-api-table-wrapper td:nth-child(3) { + width: 14%; + } + + .rest-api-table-wrapper th:nth-child(4), + .rest-api-table-wrapper td:nth-child(4) { + width: 48%; + } + } + + @media (max-width: 600px) { + .rest-api-page { + margin-top: 1.4rem; + } + + .rest-api-overview__stats { + grid-template-columns: minmax(0, 1fr); + } + + .rest-api-category-bar { + flex-wrap: nowrap; + overflow-x: auto; + padding-bottom: 0.2rem; + } + + .rest-api-category-button { + flex: 0 0 auto; + } + + .rest-api-nav-toolbar { + justify-content: stretch; + } + + .rest-api-nav-control { + width: 100%; + justify-content: center; + } + + .rest-api-nav-link__top, + .rest-api-operation__labels { + flex-wrap: wrap; + } + } +} diff --git a/assets/scss/_styles_project.scss b/assets/scss/_styles_project.scss index b4d6e8851..b1d2b2895 100644 --- a/assets/scss/_styles_project.scss +++ b/assets/scss/_styles_project.scss @@ -10,6 +10,7 @@ @import "search_project.scss"; @import "_videos_project.scss"; @import "subscription.scss"; +@import "rest-api-reference.scss"; @import "_video-landing_project.scss"; @import "elements_project"; @import "summary.scss"; diff --git a/content/en/cloud/reference/api-reference.md b/content/en/cloud/reference/api-reference.md index 6f0cda1c2..7fea14aa0 100644 --- a/content/en/cloud/reference/api-reference.md +++ b/content/en/cloud/reference/api-reference.md @@ -1,28 +1,32 @@ --- title: REST API description: > - Low-level ReST API reference for extending Layer5 Cloud. + Browse the Layer5 Cloud REST API inside the docs, powered by the shared OpenAPI schema. weight: 1 categories: [Reference] tags: [extensibility] +layout: rest-apis +display_toc: false +body_class: rest-api-reference-page +hide_readingtime: true --- To create integrations, retrieve data, and automate your cloud native infrastructure, build with the Layer5 Cloud REST API. ## Authenticating with the API -In order to authenticate to Layer5 Cloud's REST API, you need to generate and use a [security token](../security/tokens). Visit your [user account's security tokens](https://cloud.layer5.io/security/tokens) and generate a long-lived security token. Security tokens are without expiration date. You can generate as many tokens as you like. You can also revoke them at any time. +In order to authenticate to Layer5 Cloud's REST API, you need to generate and use a [security token](../security/tokens). Visit your [user account's security tokens](https://cloud.layer5.io/security/tokens) and generate a long-lived token. Security tokens remain valid until you revoke them, and you can issue as many as you need. To authenticate with the API, pass the token as a bearer token in the `Authorization` header. For example, in cURL: ```bash -curl :/// \ +curl :///api/identity/users/profile \ -H "Authorization: Bearer " ``` - Replace `` with `http` or `https` depending on your Layer5 Cloud instance. - Replace `` with the hostname or IP address of your hosted Layer5 Cloud instance. For example, [`https://cloud.layer5.io`](https://cloud.layer5.io). -- Replace `` with the API endpoint you want to access. For example, `/api/identity/users/profile`. +- Replace the path with the API endpoint you want to access. - Replace `` with the security token you generated. ## Specifying Organization Context @@ -41,11 +45,9 @@ Include the `layer5-current-orgid` header with your organization's ID to specify {{< tabpane >}} {{< tab header="cURL" >}} -curl -X POST "https://cloud.layer5.io/api/pattern" \ +curl -X GET "https://cloud.layer5.io/api/environments" \ -H "Authorization: Bearer " \ - -H "layer5-current-orgid: " \ - -H "Content-Type: application/json" \ - -d '{"name": "my-design", "pattern_file": "..."}' + -H "layer5-current-orgid: " {{< /tab >}} @@ -54,44 +56,33 @@ curl -X POST "https://cloud.layer5.io/api/pattern" \ const token = "Your-Token"; const orgId = "Your-Organization-ID"; -async function createDesign() { - const res = await fetch("https://cloud.layer5.io/api/pattern", { - method: "POST", +async function listEnvironments() { + const res = await fetch("https://cloud.layer5.io/api/environments", { + method: "GET", headers: { Authorization: `Bearer ${token}`, "layer5-current-orgid": orgId, - "Content-Type": "application/json", }, - body: JSON.stringify({ - name: "my-design", - pattern_file: "...", - }), }); const data = await res.json(); console.log(data); } -createDesign(); +listEnvironments(); {{< /tab >}} {{< tab header="Python" >}} import requests -import json -url = "https://cloud.layer5.io/api/pattern" +url = "https://cloud.layer5.io/api/environments" headers = { "Authorization": "Bearer ", - "layer5-current-orgid": "", - "Content-Type": "application/json" -} -payload = { - "name": "my-design", - "pattern_file": "..." + "layer5-current-orgid": "" } -res = requests.post(url, headers=headers, data=json.dumps(payload)) +res = requests.get(url, headers=headers) print(res.json()) {{< /tab >}} @@ -161,12 +152,6 @@ print(res.json()) {{< /tabpane >}} -## All API Endpoints - -{{< alert type="info" >}} -Open API Endpoints in new window -{{< /alert >}} - ## API Example The following example demonstrate how to retrieve information from the Academy REST APIs. @@ -270,3 +255,7 @@ This returns the number of Total registered learners: ``` 130 ``` + + +## All API Endpoints + diff --git a/layouts/docs/rest-apis.html b/layouts/docs/rest-apis.html new file mode 100644 index 000000000..27518e30c --- /dev/null +++ b/layouts/docs/rest-apis.html @@ -0,0 +1,28 @@ +{{ define "main" }} +
+

{{ .Title }}

+ {{ with .Params.description }}
{{ . | markdownify }}
{{ end }} + + {{ with .Params.plan }} + {{ partial "plan-info.html" (dict "plan" .) }} + {{ end }} + {{ .Content }} + {{ partial "rest-apis/viewer.html" . }} + {{ if (.Site.Config.Services.Disqus.Shortname) -}} +
+ {{- partial "disqus-comment.html" . -}} + {{ end -}} + {{ partial "pager.html" . }} + {{ partial "page-meta-lastmod.html" . }} +
+ +{{ partial "video-section-related.html" . -}} +
+ {{ partial "recent-discussions.html" . -}} +
+{{ end }} diff --git a/layouts/partials/rest-apis/auth-summary.html b/layouts/partials/rest-apis/auth-summary.html new file mode 100644 index 000000000..b74850f3c --- /dev/null +++ b/layouts/partials/rest-apis/auth-summary.html @@ -0,0 +1,30 @@ +{{ $operation := .operation }} +{{ $schemes := .schemes | default dict }} +{{ $summary := "" }} + +{{ if isset $operation "security" }} + {{ $security := index $operation "security" }} + {{ if not $security }} + {{ $summary = "No authentication required" }} + {{ else }} + {{ $summaries := slice }} + {{ range $security }} + {{ range $schemeName, $scopes := . }} + {{ $itemSummary := replace $schemeName "_" " " | title }} + {{ $scheme := index $schemes $schemeName }} + {{ if and $scheme (eq (lower (index $scheme "type")) "http") (eq (lower (index $scheme "scheme")) "bearer") }} + {{ $itemSummary = "Bearer JWT" }} + {{ end }} + {{ if gt (len $scopes) 0 }} + {{ $itemSummary = printf "%s (%s)" $itemSummary (delimit $scopes ", ") }} + {{ end }} + {{ if not (in $summaries $itemSummary) }} + {{ $summaries = $summaries | append $itemSummary }} + {{ end }} + {{ end }} + {{ end }} + {{ $summary = delimit $summaries " or " }} + {{ end }} +{{ end }} + +{{- $summary -}} diff --git a/layouts/partials/rest-apis/content-example.html b/layouts/partials/rest-apis/content-example.html new file mode 100644 index 000000000..54eddf28a --- /dev/null +++ b/layouts/partials/rest-apis/content-example.html @@ -0,0 +1,34 @@ +{{ $content := . }} +{{ $example := "" }} + +{{ if $content }} + {{ if isset $content "example" }} + {{ $example = index $content "example" }} + {{ else }} + {{ $examples := index $content "examples" }} + {{ if and $examples (reflect.IsMap $examples) }} + {{ range $name, $item := $examples }} + {{ if not $example }} + {{ if and (reflect.IsMap $item) (isset $item "value") }} + {{ $example = index $item "value" }} + {{ else if and (reflect.IsMap $item) (isset $item "externalValue") }} + {{ $example = index $item "externalValue" }} + {{ else }} + {{ $example = $item }} + {{ end }} + {{ end }} + {{ end }} + {{ end }} + + {{ if not $example }} + {{ $schema := index $content "schema" }} + {{ if and $schema (isset $schema "example") }} + {{ $example = index $schema "example" }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} + +{{- if $example -}} + {{- $example | jsonify -}} +{{- end -}} diff --git a/layouts/partials/rest-apis/is-operation-included.html b/layouts/partials/rest-apis/is-operation-included.html new file mode 100644 index 000000000..2f3cce004 --- /dev/null +++ b/layouts/partials/rest-apis/is-operation-included.html @@ -0,0 +1,21 @@ +{{ $operation := .operation | default . }} +{{ $audience := .audience | default "cloud" }} +{{ $xInternal := index $operation "x-internal" }} +{{ $include := false }} + +{{ if not $xInternal }} + {{ $include = true }} +{{ else }} + {{ $values := slice }} + {{ if reflect.IsSlice $xInternal }} + {{ $values = $xInternal }} + {{ else }} + {{ $values = slice $xInternal }} + {{ end }} + + {{ if in $values $audience }} + {{ $include = true }} + {{ end }} +{{ end }} + +{{- if $include -}}true{{- else -}}false{{- end -}} diff --git a/layouts/partials/rest-apis/schema-properties.html b/layouts/partials/rest-apis/schema-properties.html new file mode 100644 index 000000000..4fd5303a2 --- /dev/null +++ b/layouts/partials/rest-apis/schema-properties.html @@ -0,0 +1,35 @@ +{{ $schema := .schema | default . }} +{{ $schemas := .schemas | default dict }} +{{ $source := partial "rest-apis/schema-source.html" (dict "schema" $schema "schemas" $schemas) | transform.Unmarshal (dict "format" "json") }} +{{ $label := "Schema fields" }} +{{ $result := dict "label" $label "rows" (slice) }} + +{{ if and (not (index $source "properties")) (eq (index $source "type") "array") (index $source "items") (index (index $source "items") "properties") }} + {{ $source = index $source "items" }} + {{ $label = "Array item fields" }} + {{ $result = dict "label" $label "rows" (slice) }} +{{ end }} + +{{ $properties := index $source "properties" }} +{{ if $properties }} + {{ $required := index $source "required" | default (slice) }} + {{ $rows := slice }} + + {{ range $name, $property := $properties }} + {{ $order := 9999 }} + {{ with index $property "x-order" }} + {{ $order = . }} + {{ end }} + {{ $rows = $rows | append (dict + "name" $name + "order" $order + "schema" $property + "required" (in $required $name) + ) }} + {{ end }} + + {{ $rows = sort (sort $rows "name") "order" }} + {{ $result = dict "label" $label "rows" $rows }} +{{ end }} + +{{- $result | jsonify -}} diff --git a/layouts/partials/rest-apis/schema-source.html b/layouts/partials/rest-apis/schema-source.html new file mode 100644 index 000000000..aba7c10dd --- /dev/null +++ b/layouts/partials/rest-apis/schema-source.html @@ -0,0 +1,57 @@ +{{ $schema := .schema | default dict }} +{{ $schemas := .schemas | default dict }} + +{{ if not $schema }} + {{- dict | jsonify -}} + {{- return -}} +{{ end }} + +{{ $resolved := $schema }} + +{{ if and (reflect.IsMap $schema) (index $schema "$ref") }} + {{ $refName := replaceRE "^.*/" "" (index $schema "$ref") }} + {{ with index $schemas $refName }} + {{ $resolved = partial "rest-apis/schema-source.html" (dict "schema" . "schemas" $schemas) | transform.Unmarshal (dict "format" "json") }} + {{ end }} +{{ else if and (reflect.IsMap $schema) (index $schema "allOf") }} + {{ $properties := dict }} + {{ $required := slice }} + {{ $description := index $schema "description" | default "" }} + {{ $type := index $schema "type" | default "object" }} + + {{ range index $schema "allOf" }} + {{ $part := partial "rest-apis/schema-source.html" (dict "schema" . "schemas" $schemas) | transform.Unmarshal (dict "format" "json") }} + {{ with index $part "properties" }} + {{ $properties = merge $properties . }} + {{ end }} + {{ range (index $part "required" | default (slice)) }} + {{ if not (in $required .) }} + {{ $required = $required | append . }} + {{ end }} + {{ end }} + {{ if and (eq $description "") (index $part "description") }} + {{ $description = index $part "description" }} + {{ end }} + {{ if and (eq $type "object") (index $part "type") }} + {{ $type = index $part "type" }} + {{ end }} + {{ end }} + + {{ with index $schema "properties" }} + {{ $properties = merge $properties . }} + {{ end }} + {{ range (index $schema "required" | default (slice)) }} + {{ if not (in $required .) }} + {{ $required = $required | append . }} + {{ end }} + {{ end }} + + {{ $resolved = dict "type" $type "properties" $properties "required" $required }} + {{ if $description }} + {{ $resolved = merge $resolved (dict "description" $description) }} + {{ end }} +{{ else if and (reflect.IsMap $schema) (eq (index $schema "type") "array") (index $schema "items") }} + {{ $resolved = merge $schema (dict "items" (partial "rest-apis/schema-source.html" (dict "schema" (index $schema "items") "schemas" $schemas) | transform.Unmarshal (dict "format" "json"))) }} +{{ end }} + +{{- $resolved | jsonify -}} diff --git a/layouts/partials/rest-apis/schema-type.html b/layouts/partials/rest-apis/schema-type.html new file mode 100644 index 000000000..b1c6f59e3 --- /dev/null +++ b/layouts/partials/rest-apis/schema-type.html @@ -0,0 +1,56 @@ +{{ $schema := .schema | default . }} +{{ $schemas := .schemas | default dict }} +{{ $type := "" }} +{{ $format := "" }} + +{{ if not $schema }} + {{ $type = "" }} +{{ else if and (reflect.IsMap $schema) (index $schema "$ref") }} + {{ $refName := replaceRE "^.*/" "" (index $schema "$ref") }} + {{ $type = (replace $refName "_" " " | title) }} +{{ else }} + {{ $source := partial "rest-apis/schema-source.html" (dict "schema" $schema "schemas" $schemas) | transform.Unmarshal (dict "format" "json") }} + + {{ with index $source "format" }} + {{ $format = printf " (%s)" . }} + {{ end }} + + {{ if index $source "type" }} + {{ $type = index $source "type" }} + {{ if eq $type "array" }} + {{ $itemType := partial "rest-apis/schema-type.html" (dict "schema" (index $source "items") "schemas" $schemas) }} + {{ if $itemType }} + {{ $type = printf "array of %s" $itemType }} + {{ end }} + {{ else if eq $type "object" }} + {{ $type = "object" }} + {{ end }} + {{ else if index $source "oneOf" }} + {{ $labels := slice }} + {{ range index $source "oneOf" }} + {{ $label := index . "title" | default (partial "rest-apis/schema-type.html" (dict "schema" . "schemas" $schemas)) | default "schema" }} + {{ if not (in $labels $label) }} + {{ $labels = $labels | append $label }} + {{ end }} + {{ end }} + {{ $type = printf "one of %s" (delimit $labels ", ") }} + {{ else if index $source "properties" }} + {{ $type = "object" }} + {{ else if index $source "enum" }} + {{ $type = "enum" }} + {{ end }} + + {{ if and (index $source "nullable") $type }} + {{ $type = printf "%s | null" $type }} + {{ end }} + + {{ if and $type $format (not (strings.Contains $type $format)) }} + {{ $type = printf "%s%s" $type $format }} + {{ end }} + + {{ if not $type }} + {{ $type = "schema" }} + {{ end }} +{{ end }} + +{{- $type -}} diff --git a/layouts/partials/rest-apis/spec.html b/layouts/partials/rest-apis/spec.html new file mode 100644 index 000000000..aa6728035 --- /dev/null +++ b/layouts/partials/rest-apis/spec.html @@ -0,0 +1,17 @@ +{{ $candidates := slice }} +{{ $candidates = $candidates | append "data/openapi.yml" }} + +{{ $resolvedPath := "" }} +{{ range $candidate := $candidates }} + {{ if and (eq $resolvedPath "") (os.FileExists $candidate) }} + {{ $resolvedPath = $candidate }} + {{ end }} +{{ end }} + +{{ if eq $resolvedPath "" }} + {{ errorf "Unable to load REST API spec. Checked: %s" (delimit $candidates ", ") }} +{{ end }} + +{{ $opts := dict "format" "yaml" }} +{{ $spec := os.ReadFile $resolvedPath | transform.Unmarshal $opts }} +{{- $spec | jsonify -}} diff --git a/layouts/partials/rest-apis/tag-meta.html b/layouts/partials/rest-apis/tag-meta.html new file mode 100644 index 000000000..fa5f47f7e --- /dev/null +++ b/layouts/partials/rest-apis/tag-meta.html @@ -0,0 +1,34 @@ +{{ $name := .name | default "Ungrouped" }} +{{ $tags := .tags | default dict }} +{{ $meta := index $tags $name }} + +{{ $rawLabel := "" }} +{{ $description := "" }} + +{{ if $meta }} + {{ $rawLabel = index $meta "x-displayName" | default "" }} + {{ $description = index $meta "description" | default "" }} +{{ end }} + +{{ $fallback := index (split $name "_") 0 | default $name }} + +{{ if or (eq $rawLabel "") (eq (lower $rawLabel) "other") (and (eq (lower $rawLabel) "users") (not (strings.HasPrefix $name "User_"))) }} + {{ $rawLabel = $fallback }} +{{ end }} + +{{ if eq $rawLabel "" }} + {{ $rawLabel = "Ungrouped" }} +{{ end }} + +{{ if strings.Contains (lower $description) "meshery cloud" }} + {{ $description = "" }} +{{ end }} + +{{ $label := replace $rawLabel "_" " " }} +{{ if ne $label "" }} + {{ $label = $label | title }} +{{ else }} + {{ $label = "Ungrouped" }} +{{ end }} + +{{- (dict "name" $name "label" $label "description" $description) | jsonify -}} diff --git a/layouts/partials/rest-apis/tag-subsection-meta.html b/layouts/partials/rest-apis/tag-subsection-meta.html new file mode 100644 index 000000000..b279fd5d2 --- /dev/null +++ b/layouts/partials/rest-apis/tag-subsection-meta.html @@ -0,0 +1,23 @@ +{{ $name := .name | default "Ungrouped" }} +{{ $tags := .tags | default dict }} +{{ $meta := index $tags $name }} + +{{ $rawLabel := "" }} + +{{ if $meta }} + {{ $rawLabel = index $meta "x-displayName" | default "" }} +{{ end }} + +{{ if eq $rawLabel "" }} + {{ $parts := split $name "_" }} + {{ $rawLabel = index $parts (sub (len $parts) 1) | default $name }} +{{ end }} + +{{ $label := replace $rawLabel "_" " " }} +{{ if ne $label "" }} + {{ $label = $label | title }} +{{ else }} + {{ $label = "Ungrouped" }} +{{ end }} + +{{- (dict "name" $name "label" $label) | jsonify -}} diff --git a/layouts/partials/rest-apis/viewer.html b/layouts/partials/rest-apis/viewer.html new file mode 100644 index 000000000..c8d73a9f3 --- /dev/null +++ b/layouts/partials/rest-apis/viewer.html @@ -0,0 +1,1142 @@ +{{ $spec := partial "rest-apis/spec.html" . | transform.Unmarshal (dict "format" "json") }} +{{ $components := index $spec "components" | default dict }} +{{ $securitySchemes := index $components "securitySchemes" | default dict }} +{{ $schemas := index $components "schemas" | default dict }} +{{ $tagGroups := index $spec "x-tagGroups" | default (slice) }} +{{ $specURL := "https://github.com/layer5io/docs/blob/master/data/openapi.yml" }} +{{ $defaultCloudServer := dict + "url" "https://cloud.layer5.io" + "description" "Layer5 Cloud default URL" +}} +{{ $tagIndex := dict }} +{{ range $spec.tags }} + {{ $tagIndex = merge $tagIndex (dict .name .) }} +{{ end }} + +{{ $methodOrder := slice "get" "post" "put" "patch" "delete" "options" "head" }} +{{ $operations := slice }} +{{ $tagCounts := dict }} +{{ $cloudOnlyCount := 0 }} +{{ $sharedCount := 0 }} + +{{ range $path, $route := $spec.paths }} + {{ range $methodOrder }} + {{ $method := . }} + {{ with index $route $method }} + {{ $operation := . }} + {{ $includeOperation := eq (partial "rest-apis/is-operation-included.html" (dict "operation" $operation "audience" "cloud") | strings.TrimSpace) "true" }} + {{ $xInternal := index $operation "x-internal" }} + {{ if $includeOperation }} + {{ $servers := index $operation "servers" | default (index $route "servers") | default ($spec.servers | default (slice)) }} + {{ $tagName := "Ungrouped" }} + {{ with $operation.tags }} + {{ $tagName = index . 0 }} + {{ end }} + {{ $tagMeta := partial "rest-apis/tag-meta.html" (dict "name" $tagName "tags" $tagIndex) | transform.Unmarshal (dict "format" "json") }} + {{ $pathSlug := replaceRE "[{}]" "" $path }} + {{ $pathSlug = replaceRE "[^a-zA-Z0-9]+" "-" $pathSlug }} + {{ $pathSlug = lower $pathSlug }} + {{ $pathSlug = replaceRE "^-+|-+$" "" $pathSlug }} + {{ if eq $pathSlug "" }} + {{ $pathSlug = "root" }} + {{ end }} + {{ $operationID := printf "%s-%s" $method $pathSlug }} + {{ $isShared := not $xInternal }} + + {{ if $isShared }} + {{ $sharedCount = add $sharedCount 1 }} + {{ else }} + {{ $cloudOnlyCount = add $cloudOnlyCount 1 }} + {{ end }} + + {{ $operations = $operations | append (dict + "id" $operationID + "pathId" $pathSlug + "path" $path + "method" $method + "summary" ($operation.summary | default $path) + "description" $operation.description + "tag" $tagName + "tagLabel" (index $tagMeta "label") + "tagDescription" (index $tagMeta "description") + "isShared" $isShared + "servers" $servers + "data" $operation + ) }} + + {{ $count := index $tagCounts $tagName | default 0 }} + {{ $tagCounts = merge $tagCounts (dict $tagName (add $count 1)) }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} + +{{ $orderedTags := slice }} +{{ range $tagGroup := $tagGroups }} + {{ range $tagName := ($tagGroup.tags | default (slice)) }} + {{ if and (gt ((index $tagCounts $tagName) | default 0) 0) (not (in $orderedTags $tagName)) }} + {{ $orderedTags = $orderedTags | append $tagName }} + {{ end }} + {{ end }} +{{ end }} +{{ range $spec.tags }} + {{ $tagName := .name }} + {{ if and (gt ((index $tagCounts $tagName) | default 0) 0) (not (in $orderedTags $tagName)) }} + {{ $orderedTags = $orderedTags | append $tagName }} + {{ end }} +{{ end }} +{{ range $operations }} + {{ if not (in $orderedTags .tag) }} + {{ $orderedTags = $orderedTags | append .tag }} + {{ end }} +{{ end }} + +{{ if gt (len $operations) 0 }} +
+
+

Layer5 Cloud REST API reference

+

+ {{ len $operations }} API endpoints across {{ len $orderedTags }} categories. + This reference is generated from the OpenAPI schema used by the Layer5 docs. +

+
    +
  • {{ len $orderedTags }}categories
  • +
  • {{ len $operations }}endpoints
  • +
  • SchemaView OpenAPI source
  • +
+
+ +
+ + +
+

Categories

+
+ + {{ range $tagName := $orderedTags }} + {{ $tagMeta := partial "rest-apis/tag-meta.html" (dict "name" $tagName "tags" $tagIndex) | transform.Unmarshal (dict "format" "json") }} + + {{ end }} +
+
+ +
+

Showing all endpoints.

+
+
+ +
+ + +
+
+
+
+ Ready to explore +
+

Select an endpoint

+

+ Open a category, choose a tag, and pick an endpoint to view its request and response details here. +

+
+
+ {{ range $operations }} + {{ $operationId := .id }} + {{ $operation := .data }} + {{ $operationPath := .path }} + {{ $authSummary := partial "rest-apis/auth-summary.html" (dict "operation" $operation "schemes" $securitySchemes) | strings.TrimSpace }} + {{ $parameters := $operation.parameters | default (slice) }} + {{ $servers := .servers | default (slice) }} + {{ if eq (len $servers) 0 }} + {{ $servers = $servers | append $defaultCloudServer }} + {{ end }} + +
+
+
+ {{ upper .method }} + {{ .tagLabel }} + {{ if .isShared }}Shared{{ else }}Cloud{{ end }} +
+

{{ .path }}

+

{{ .summary }}

+ {{ with .description }} +
{{ . | markdownify }}
+ {{ end }} +
+ + {{ if $authSummary }} +
+
+
Authentication
+
{{ $authSummary }}
+
+
+ {{ end }} + +
+
+

Base URLs

+

Try this endpoint

+

+ Substitute your own Layer5 Cloud hostname when you are working against a hosted or self-managed instance. +

+
+
+ {{ range $server := $servers }} + {{ $serverUrl := index $server "url" | default "" }} + {{ $serverDescription := index $server "description" | default "Layer5 Cloud URL" }} +
+

{{ $serverDescription }}

+ {{ printf "%s%s" $serverUrl $operationPath }} +
+ {{ end }} +
+
+ + {{ if gt (len $parameters) 0 }} +
+

Parameters

+ {{ $locations := slice + (dict "key" "path" "label" "Path parameters") + (dict "key" "query" "label" "Query parameters") + (dict "key" "header" "label" "Header parameters") + (dict "key" "cookie" "label" "Cookie parameters") + }} + {{ range $locations }} + {{ $rows := where $parameters "in" .key }} + {{ if gt (len $rows) 0 }} +
+

{{ .label }}

+
+ + + + + + + + + + + {{ range $rows }} + {{ $parameterSchema := index . "schema" | default dict }} + {{ $parameterType := partial "rest-apis/schema-type.html" (dict "schema" $parameterSchema "schemas" $schemas) | strings.TrimSpace }} + + + + + + + {{ end }} + +
NameTypeRequiredDescription
{{ .name }}{{ $parameterType | default "schema" }}{{ if .required }}Yes{{ else }}No{{ end }} + {{ with .description }} + {{ . | markdownify }} + {{ else }} + No description provided. + {{ end }} +
+
+
+ {{ end }} + {{ end }} +
+ {{ end }} + + {{ with $operation.requestBody }} + {{ $requestBody := . }} +
+

Request body

+ {{ with $requestBody.description }} +
{{ . | markdownify }}
+ {{ end }} + {{ range $contentType, $content := $requestBody.content }} + {{ $schema := index $content "schema" | default dict }} + {{ $schemaType := partial "rest-apis/schema-type.html" (dict "schema" $schema "schemas" $schemas) | strings.TrimSpace }} + {{ $fields := partial "rest-apis/schema-properties.html" (dict "schema" $schema "schemas" $schemas) | transform.Unmarshal (dict "format" "json") }} + {{ $example := "" }} + {{ $exampleJSON := partial "rest-apis/content-example.html" $content | strings.TrimSpace }} + {{ if ne $exampleJSON "" }} + {{ $example = $exampleJSON | transform.Unmarshal (dict "format" "json") }} + {{ end }} +
+
+
+

{{ $contentType }}

+

Schema: {{ $schemaType }}

+
+ {{ if $requestBody.required }}Required{{ else }}Optional{{ end }} +
+ + {{ $requestSchema := partial "rest-apis/schema-source.html" (dict "schema" $schema "schemas" $schemas) | transform.Unmarshal (dict "format" "json") }} + {{ with index $requestSchema "description" }} +
{{ . | markdownify }}
+ {{ end }} + + {{ if gt (len (index $fields "rows")) 0 }} +
+ + + + + + + + + + + {{ range index $fields "rows" }} + + + + + + + {{ end }} + +
FieldTypeRequiredDescription
{{ .name }}{{ partial "rest-apis/schema-type.html" (dict "schema" (index . "schema") "schemas" $schemas) | strings.TrimSpace }}{{ if .required }}Yes{{ else }}No{{ end }} + {{ with index .schema "description" }} + {{ . | markdownify }} + {{ else }} + No description provided. + {{ end }} +
+
+ {{ else if index $schema "oneOf" }} +
+ {{ range index $schema "oneOf" }} + {{ $variantFields := partial "rest-apis/schema-properties.html" (dict "schema" . "schemas" $schemas) | transform.Unmarshal (dict "format" "json") }} + {{ $variantType := partial "rest-apis/schema-type.html" (dict "schema" . "schemas" $schemas) | strings.TrimSpace }} +
+

{{ index . "title" | default $variantType }}

+ {{ with index . "description" }} +
{{ . | markdownify }}
+ {{ end }} + {{ if gt (len (index $variantFields "rows")) 0 }} +
+ + + + + + + + + + + {{ range index $variantFields "rows" }} + + + + + + + {{ end }} + +
FieldTypeRequiredDescription
{{ .name }}{{ partial "rest-apis/schema-type.html" (dict "schema" (index . "schema") "schemas" $schemas) | strings.TrimSpace }}{{ if .required }}Yes{{ else }}No{{ end }} + {{ with index .schema "description" }} + {{ . | markdownify }} + {{ else }} + No description provided. + {{ end }} +
+
+ {{ else }} +

Schema: {{ partial "rest-apis/schema-type.html" (dict "schema" . "schemas" $schemas) | strings.TrimSpace }}

+ {{ end }} +
+ {{ end }} +
+ {{ else }} +

Schema: {{ $schemaType }}

+ {{ end }} + + {{ if $example }} +
+

Example payload

+
{{ if or (reflect.IsMap $example) (reflect.IsSlice $example) }}{{ $example | jsonify (dict "indent" "  ") }}{{ else }}{{ $example }}{{ end }}
+
+ {{ end }} +
+ {{ end }} +
+ {{ end }} + + {{ with $operation.responses }} +
+
+

Returned data

+

Responses

+

+ Status codes, content types, and response schemas returned by this endpoint. +

+
+ {{ range $code, $response := . }} + {{ $statusCode := printf "%v" $code }} + {{ $responseTone := "neutral" }} + {{ if strings.HasPrefix $statusCode "2" }} + {{ $responseTone = "success" }} + {{ else if strings.HasPrefix $statusCode "3" }} + {{ $responseTone = "info" }} + {{ else if strings.HasPrefix $statusCode "4" }} + {{ $responseTone = "warning" }} + {{ else if strings.HasPrefix $statusCode "5" }} + {{ $responseTone = "danger" }} + {{ end }} + +
+
+ {{ $statusCode }} +
+ {{ with $response.description }} + {{ . | markdownify }} + {{ else }} +

No description provided.

+ {{ end }} +
+
+ + {{ with $response.content }} + {{ range $contentType, $content := . }} + {{ $schema := index $content "schema" | default dict }} + {{ $schemaType := partial "rest-apis/schema-type.html" (dict "schema" $schema "schemas" $schemas) | strings.TrimSpace }} + {{ $fields := partial "rest-apis/schema-properties.html" (dict "schema" $schema "schemas" $schemas) | transform.Unmarshal (dict "format" "json") }} + {{ $example := "" }} + {{ $exampleJSON := partial "rest-apis/content-example.html" $content | strings.TrimSpace }} + {{ if ne $exampleJSON "" }} + {{ $example = $exampleJSON | transform.Unmarshal (dict "format" "json") }} + {{ end }} +
+
+
+

{{ $contentType }}

+

Schema: {{ $schemaType }}

+
+
+ + {{ $responseSchema := partial "rest-apis/schema-source.html" (dict "schema" $schema "schemas" $schemas) | transform.Unmarshal (dict "format" "json") }} + {{ with index $responseSchema "description" }} +
{{ . | markdownify }}
+ {{ end }} + + {{ if gt (len (index $fields "rows")) 0 }} +
+ + + + + + + + + + + {{ range index $fields "rows" }} + + + + + + + {{ end }} + +
FieldTypeRequiredDescription
{{ .name }}{{ partial "rest-apis/schema-type.html" (dict "schema" (index . "schema") "schemas" $schemas) | strings.TrimSpace }}{{ if .required }}Yes{{ else }}No{{ end }} + {{ with index .schema "description" }} + {{ . | markdownify }} + {{ else }} + No description provided. + {{ end }} +
+
+ {{ else if index $schema "oneOf" }} +
+ {{ range index $schema "oneOf" }} + {{ $variantFields := partial "rest-apis/schema-properties.html" (dict "schema" . "schemas" $schemas) | transform.Unmarshal (dict "format" "json") }} + {{ $variantType := partial "rest-apis/schema-type.html" (dict "schema" . "schemas" $schemas) | strings.TrimSpace }} +
+

{{ index . "title" | default $variantType }}

+ {{ with index . "description" }} +
{{ . | markdownify }}
+ {{ end }} + {{ if gt (len (index $variantFields "rows")) 0 }} +
+ + + + + + + + + + + {{ range index $variantFields "rows" }} + + + + + + + {{ end }} + +
FieldTypeRequiredDescription
{{ .name }}{{ partial "rest-apis/schema-type.html" (dict "schema" (index . "schema") "schemas" $schemas) | strings.TrimSpace }}{{ if .required }}Yes{{ else }}No{{ end }} + {{ with index .schema "description" }} + {{ . | markdownify }} + {{ else }} + No description provided. + {{ end }} +
+
+ {{ else }} +

Schema: {{ partial "rest-apis/schema-type.html" (dict "schema" . "schemas" $schemas) | strings.TrimSpace }}

+ {{ end }} +
+ {{ end }} +
+ {{ else }} +

Schema: {{ $schemaType }}

+ {{ end }} + + {{ if $example }} +
+

Example response

+
{{ if or (reflect.IsMap $example) (reflect.IsSlice $example) }}{{ $example | jsonify (dict "indent" "  ") }}{{ else }}{{ $example }}{{ end }}
+
+ {{ end }} +
+ {{ end }} + {{ end }} +
+ {{ end }} +
+ {{ end }} +
+ {{ end }} +
+
+
+{{ else }} +

No Layer5 Cloud REST operations were found in the shared OpenAPI schema.

+{{ end }} + +