# OpenAPI specifications

Specifications generated from your data models - downloads, the HTTP endpoint and the console.

The platform generates OpenAPI specifications for your REST APIs - definitions of endpoints, request and response schemas and security requirements in the standard format that Postman, API gateways and code generators understand.

The specifications are built from [data models](https://zato.io/docs/dev/examples/model.html) defined in your services. When you assign a model to a service's `input` or `output`, Zato extracts the schema information from the dataclass and puts it in the generated document.

## OpenAPI console {#openapi-console}

The primary interface is the OpenAPI console - a live, browsable portal where the document is generated from the deployed services themselves, filtered per caller and paired with a try-it client. It requires no channels, no exports and no configuration:

- [Using the OpenAPI console](https://zato.io/docs/dev/rest/openapi-console.html) - for API consumers, signing in, browsing and invoking endpoints
- [OpenAPI administration](https://zato.io/docs/dev/api-management/openapi.html) - for operators, architecture, which channels are documented, branding
- [OpenAPI and API management](https://zato.io/openapi.html) - the overview of the whole layer
- [API management documentation](https://zato.io/docs/api-management/index.html) - everything else the layer includes, from [quota tiers](https://zato.io/docs/security/quota-tiers.html) to analytics

Independently of the console, you can also produce downloadable specification files in two ways:

- **Dashboard** - download OpenAPI YAML files directly from the web interface
- **OpenAPI endpoint** - access specifications over HTTP with authentication

**Dashboard**

## Create an OpenAPI channel {#create-an-openapi-channel}

An OpenAPI channel groups multiple REST channels into a single API specification. To create one, go to **Connections** > **Channels** > **OpenAPI** in the Dashboard, click **Create an OpenAPI channel** and fill in the form:

1. **Name:** My API v2
2. **REST channels:** the channels to include in this specification
3. Click **OK**

![New OpenAPI channel](https://zatosource-production.b-cdn.net/docs/gfx/rest/openapi-channel-create.webp?v=1790440701)

Dashboard menu: Connections > Channels > OpenAPI

The channel name is slugified into the URL path of the OpenAPI endpoint - a channel named `My API v2` becomes accessible at `/openapi/my-api-v2`.

## Assign REST channels {#assign-rest-channels}

In the OpenAPI channel's edit form, the REST channels section lists every REST channel with a tri-state checkbox:

- **On** - the channel appears in the specification
- **Off** - the channel does not appear
- **Disabled** (an "x" sign) - the channel is temporarily excluded, kept in the list for when it returns

Only channels marked **On** appear in the generated specification, and a single REST channel may be part of more than one OpenAPI channel.

## Download the specification {#download-the-specification}

In the channel list under **Connections** > **Channels** > **OpenAPI**, each channel's row has a **Download OpenAPI** link that serves the complete YAML file, containing:

- API paths and HTTP methods
- Request body schemas, from your service `input` definitions
- Response schemas, from your service `output` definitions
- Security schemes - the [Basic Auth](https://zato.io/docs/security/basic-auth.html) and [API key](https://zato.io/docs/security/api-keys.html) definitions of the REST channels

## Example output {#example-output}

A service with typed input and output models:

```python
# -*- coding: utf-8 -*-

# stdlib
from dataclasses import dataclass

# Zato
from zato.server.service import Model, Service

@dataclass(init=False)
class GetCustomerRequest(Model):
    customer_id: str

@dataclass(init=False)
class GetCustomerResponse(Model):
    name: str
    email: str

class GetCustomer(Service):
    name = 'customer.get'

    input = GetCustomerRequest
    output = GetCustomerResponse

    def handle(self) -> 'None':
        pass
```

The generated specification includes the full schemas:

```yaml
openapi: 3.1.0
info:
  title: My API
  version: 1.0.0
paths:
  /api/customer:
    post:
      summary: Invoke customer.get
      operationId: customer_get
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GetCustomerRequest'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetCustomerResponse'
      security:
        - my-basic-auth: []
components:
  schemas:
    GetCustomerRequest:
      type: object
      properties:
        customer_id:
          type: string
      required:
        - customer_id
    GetCustomerResponse:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
      required:
        - name
        - email
  securitySchemes:
    my-basic-auth:
      type: http
      scheme: basic
```

**OpenAPI endpoint**

## Access OpenAPI over HTTP {#access-openapi-over-http}

Each OpenAPI channel is served at its own HTTP endpoint:

```text
GET /openapi/{channel-name}
```

The endpoint requires HTTP Basic Auth credentials matching one of the REST channels included in the OpenAPI channel - if any of those channels has a Basic Auth security definition, its credentials open the specification:

```bash
curl -u username:password http://localhost:11223/openapi/my-api
```

A request with missing or invalid credentials receives HTTP 403 Forbidden.

## Example {#example}

With an OpenAPI channel named `my-api` and a REST channel secured by a Basic Auth definition whose username is `apiuser`:

```bash
curl -u apiuser:secret123 http://localhost:11223/openapi/my-api
```

Response:

```yaml
openapi: 3.1.0
info:
  title: my-api
  version: 1.0.0
paths:
  /api/customer:
    post:
      summary: Invoke customer.get
      operationId: customer_get
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetCustomerResponse'
      security:
        - pubapi: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GetCustomerRequest'
components:
  schemas:
    GetCustomerRequest:
      type: object
      properties:
        customer_id:
          type: string
      required:
        - customer_id
    GetCustomerResponse:
      type: object
      properties:
        name:
          type: string
        email:
          type: string
      required:
        - name
        - email
  securitySchemes:
    pubapi:
      type: http
      scheme: basic
```

## See also {#see-also}

- [OpenAPI console](https://zato.io/docs/dev/rest/openapi-console.html) - The live documentation portal with a try-it client
- [REST channels](https://zato.io/docs/dev/rest/channels.html) - The channels and data models the specifications describe
- [Authentication](https://zato.io/docs/dev/rest/authentication.html) - The security definitions the specifications document
- [API versioning](https://zato.io/docs/dev/rest/versioning.html) - How deprecated endpoints appear to specification readers

## Learn more {#learn-more}

- [REST integration overview](https://zato.io/integrations/rest/) - Start here to see how teams build REST integrations
- [In-depth API tutorial](https://zato.io/tutorials/main/01.html) - Master architectural patterns for production-ready integrations
- [Modern REST API tutorial](https://zato.io/tutorials/rest-api/python.html) - Design, build and secure REST APIs with Python
