# Using OpenApi to describe your services

> An overview of how to connect data sources to Orbital

Source: https://orbitalhq.com/docs/describing-data-sources/open-api

Orbital can use OpenApi specs to understand what APIs exist, and how to call them.

Orbital uses [Semantic schemas](/docs/introduction#semantic-data-schemas) to describe how data relates between systems. For OpenAPI, this
means enriching return types and input parameters with metadata to describe them semantically.

To do this, we embed Taxi metadata within the OpenApi specs.

## Adding Taxi annotations to OpenApi specs
Taxi annotations use a custom `x-taxi-type` block within OpenApi specs.

Example:

```yaml
x-taxi-type:
  # The name of the type
  name: com.acme.MyType
  # Optional.  Indicates if the type should be created if not already present.
  create: false
```

The `create` element is optional, and overrides the default behaviour.

If `create` is set to `false`, then schemas which attempt to publish types that aren't already defined on the schema server
are rejected as compilation errors.

This is to prevent accidental typos.

However, the default behaviour for `create` is different between response models and attribute types:

| Entity type           | Default `create` behaviour | Impact                                                                                                             |
|-----------------------|----------------------------|--------------------------------------------------------------------------------------------------------------------|
| Model (Response type) | `true`                     | By default, if the model isn't already present within the schema, it's created.                                    |
| Attribute             | `false`                    | By default, if an attribute type isn't already present within the remote schema, then the OpenApi spec is rejected |

### Describing response types
Response models returned from API calls can be enriched to include semantic metadata

#### Assigning Taxi type names to models
You can optionally define a custom type name for response types being published to Orbital.
If omitted, then the type name is inferred from the rest of the schema

```yaml
  components:
    schemas:
      Pet:
        # Assign a Taxi type name to the model.
        # Optional
>       x-taxi-type:
>         name: petstore.Pet
        # Everything else is standard OpenApi spec...
        allOf:
          - $ref: '#/components/schemas/NewPet'
          - required:
```

#### Adding type annotations to attributes
Enrich attributes with semantic type metadata

```yaml

      NewPet:
        required:
          - name
        properties:
          name:
>           x-taxi-type:
>             name: petstore.Name
            type: string
          tag:
>           x-taxi-type:
>             name: petstore.Tag
            type: string
```

By default, it's expected that types referred to in `x-taxi-type` within attributes have already been defined on the schema server, as part of your
[core taxonomy](/docs/introduction).

However, if you are intentionally publishing new types from your OpenApi spec, then set `create` to `true`:

```yaml
      NewPet:
        required:
          - name
        properties:
          name:
>           x-taxi-type:
>             name: petstore.Name
>             # petstore.Name will be created if not present
>             create: true
            type: string
```

### Describing service parameters
Inputs into services can also be enriched, to annotate the semantic data required.

Simply add a `x-taxi-type` annotation to each input, containing a `name` attribute with a reference to the name of the type from your [core taxonomy](/docs/introduction)

```yaml
  ## ... OpenApi spec trimmed...
  paths:
    /pets/{id}:
      get:
        description: Returns a user based on a single ID, if the user does not have access to the pet
        operationId: find pet by id
        parameters:
          - name: id
            in: path
            description: ID of pet to fetch
            required: true
            schema:
              type: integer
              format: int64
>             x-taxi-type:
>               name: petstore.PetId  # <-- Name of type from core taxonomy
```

## Publishing OpenAPI specs to Orbital
Once you have added taxi annotations to your OpenApi spec, you're ready to publish it to Orbital.

### Different ways to publish OpenAPI specs

There are a few different ways to expose your OpenAPI spec to Orbital, each which suits different team workflows.

| Approach                                                                                          | Description                                                                                                                                                           | Suits teams who...                                                                                       | Considerations                                                                                                                    |
|---------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
| Importing through the UI [docs](#importing-through-the-ui)                                        | Converts the OpenAPI spec to Taxi, and stores it within your Taxi project.                                                                                            | Good for teams that prefer to work in Taxi                                                               | Changes made to the OpenAPI spec **are not** reflected in your Taxi automatically, you'll need to re-import                       |
| Reading from a git repo [docs](/docs/workspace/connecting-a-git-repo#reading-open-api-specs-from-git) | Declares the OpenAPI spec as a project in your workspace.   Keeps the OpenAPI spec as a source-of-truth, and allows a team to evolve the spec independently | Best for distributed teams or federating multiple APIs, where teams evolve their API specs independently | Changes made to the OpenAPI spec **are** automatically detected    Requires adding Taxi annotations to the OpenAPI spec |
| Mixing OpenAPI and Taxi in the same project [docs](#combining-openapi-and-taxi-in-a-single-project) | Keeps your OpenAPI spec as source-of-truth, but stores alongside other Taxi sources                                                                                   | Best when a single team owns/manages Orbital, and wants a mono-repo approach                             | Changes made to the OpenAPI spec **are** automatically detected    Requires adding Taxi annotations to the OpenAPI spec |

### Combining OpenAPI and Taxi in a single project

You can configure your Taxi project to read OpenAPI specs directly by defining their location in the `additionalSources` section of your `taxi.conf` file.

Example directory structure:

```
.
├── src/           # Taxi files
├── openapi/       # OpenAPI specs
└── taxi.conf
```

Configure in your `taxi.conf`:

```hocon taxi.conf
name: com.example/my-taxi-project
version: 0.2.0
sourceRoot: src/
additionalSources: {
  "@orbital/openapi" : "openapi/*.yaml"
}
```

#### OpenAPI-specific configuration

_Available since 0.37_

You can optionally provide additional metadata for your OpenAPI spec by creating a `.taxi.conf` file with the same name as your spec.

If no config file is provided, Orbital will use the project's organization as the default namespace.

| Property             | Example               | Description                                                                                                                                   | Default                    |
|----------------------|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|
| `defaultNamespace`   | `com.petflix.pets`    | The namespace for any types, models or services declared in this OpenAPI spec                                                                 | Project organization name  |
| `serviceBasePath`    | `https://petflix.com` | The base url for any HTTP operations which do not include one. Not required if paths are all absolute, or the API spec provides a base server | `null`                     |

Example file structure:

```
openapi/
├── petflix-api-spec.yaml       # Your OpenAPI spec
└── petflix-api-spec.taxi.conf  # Optional configuration file
```

Configuration file contents:

```hocon petflix-api-spec.taxi.conf
defaultNamespace: "com.petflix.pets"
serviceBasePath: "https://petflix.com"
```

### Guide: Importing OpenAPI projects via the UI

**Note**
Before you can import an OpenApi spec into Orbital, you need to ensure you have configured an editable Schema source
    - either a
    local [disk repository](/docs/workspace/connecting-a-disk-repo) or
    a [git repository](/docs/workspace/connecting-a-git-repo)

    Be sure to enable editing of the repository when adding it.

    This lets Orbital store the converted OpenApi spec, with some additional metadata that it creates when importing

Navigate to [/data-source-manager/add](http://localhost:9022/data-source-manager/add) within your Orbital UI.

Next, select a project to import into, then choose "Swagger / Open API" from the data source dropdown.

 * Either provide the OpenApi spec file directly, or enter a Url to load the spec from.
 * Provide a default namespace.  (eg: `com.petflix.pets`).  Services from your OpenAPI spec are imported into this namespace
 * If your OpenAPI spec doesn't define a base url (ie.,: `servers/url`), then specify a Base url.  All paths in the OpenApi spec are treated as relative to this path.
 * Then click Configure

#### Preview your imported schema

Your imported OpenApi spec will be available for you to browse, to make sure everything looks correct.

Any types that have been defined as `create: true` within the Yaml spec should appear wihtin the Types section.

Services and operations should've been created for all endpoints within your OpenApi spec.

At this point, you can edit types (by clicking on the
pencil icon next to the type name) to further refine your schema.
Once you're happy, click Save, and the OpenApi spec will be imported.
