Working with other API specs

OpenAPI Integration

​
Overview

Taxi can be embedded within OpenAPI specifications to add semantic meaning to APIs. This allows you to:

  • Define semantic types for request/response models
  • Add semantic meaning to API parameters
  • Create a unified semantic layer across multiple APIs

Semantic Enhancement

OpenAPI specs describe API structure. Taxi enhances them with semantic meaning, enabling better data discovery and integration.

​
Adding Taxi to OpenAPI

​
Basic Syntax

Taxi metadata is added using x-taxi-type extensions in your OpenAPI spec:

x-taxi-type:
  name: com.acme.MyType    # The semantic type name
  create: false            # Optional flag to control type creation

​
Type Creation Behavior

The create flag controls whether new types are created if they don’t exist.

The default behaviour varies between models and field attributes - and defaults to the reccomended best practice for each.

ContextDefaultBehavior
Response ModelstrueCreates new types if not found
Field AttributesfalseRequires types to exist

Type Creation

<p>Semantic types let you share data between systems, while avoiding tight coupling. Try to use existing types (where the semantics match), or create new types in a shared taxonomy - rather than creating types in your OpenAPI spec</p> <p>Only create new types (<code>create: true</code>) when you're intentionally extending your semantic model, or creating a type you're not ready to share yet.</p>

​
Adding annotations

Use x-taxi-annotations to add annotations to the generated Taxi. It’s a list of strings, each written in Taxi’s annotation syntax:

components:
  schemas:
    Person:
      x-taxi-annotations: ["@Entity(table = \"people\")"]
      properties:
        id:
          type: string
          x-taxi-annotations: ["@Id", "@Cache(ttl = 30)"]

generates:

@Entity(table = "people")
closed model Person {
   @Id
   @Cache(ttl = 30)
   id : String
}
  • On a property, the annotations go on the field. On a schema in components/schemas, they go on the model or type generated from it.
  • On an operation, a parameter or a request body, they go on the generated operation or its parameter (see Annotating operations and parameters).
  • x-taxi-annotations is separate from x-taxi-type, so you can annotate a field whether or not you declare its type.
  • One string can hold several annotations: x-taxi-annotations: "@Id @Cache(ttl = 30)".
  • Parameter values can be strings, numbers or booleans.
  • Annotation names aren’t checked when the spec is read. They’re resolved when the generated Taxi is compiled, like any other annotation, so an annotation type that isn’t declared anywhere is still allowed.
  • An entry that isn’t valid annotation syntax is left out, and reported as a warning.

​
Annotating a property that uses $ref

OpenAPI 3.1 keeps keys written next to a $ref, so you can annotate a referenced property directly:

# OpenAPI 3.1
id:
  $ref: '#/components/schemas/PersonId'
  x-taxi-annotations: ["@Id"]

OpenAPI 3.0 ignores everything next to a $ref, and the annotations are dropped (with a warning). In 3.0, wrap the reference in an allOf and put the annotations next to the allOf. The field is still typed as the referenced schema:

# OpenAPI 3.0
id:
  allOf:
    - $ref: '#/components/schemas/PersonId'
  x-taxi-annotations: ["@Id"]

​
Annotating operations and parameters

Add x-taxi-annotations to an operation, a parameter, or a request body:

paths:
  /customers/{id}:
    get:
      operationId: getCustomer
      x-taxi-annotations: ["@Cached(ttl = 30)"]
      parameters:
        - name: id
          in: path
          required: true
          x-taxi-annotations: ["@Id"]
          schema:
            type: string
    put:
      operationId: updateCustomer
      requestBody:
        x-taxi-annotations: ["@Audited"]
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Customer'

generates:

service CustomersIdService {
   @taxi.http.HttpOperation(method = "GET" , url = "http://acme.com/customers/{id}")
   @Cached(ttl = 30)
   operation getCustomer(
      @taxi.http.PathVariable(value = "id")
      @Id id : String
   ) : Customer
   // ...
}
  • Put a parameter’s annotations on the parameter itself, next to name and in, not on its schema. Annotations on a parameter’s schema are ignored, with a warning.
  • A parameter declared on the path item applies to every operation on that path, and so do its annotations.
  • A parameter declared in components/parameters and used with $ref takes its annotations from the component. Every operation that uses it gets them.
  • Your annotations come after the ones Taxi generates from the spec: @HttpOperation, @PathVariable, @QueryVariable, @HttpHeader and @RequestBody. These say how the operation is called (its method, its URL, and the name each parameter is sent as), so you can’t replace them. If you declare one with the same name (with or without the taxi.http namespace), yours is ignored, with a warning.

​
Declaring operation kinds

Some TaxiQL behavior depends on whether operations are read-only or write operations (sometimes referred to as ‘mutations’).

By default:

  • GET, HEAD, and OPTIONS methods are treated as read operations (default, no modifier)
  • POST, PUT, PATCH, and DELETE methods are treated as write operations

You can override this default behavior using x-taxi-operation-kind at the operation level:

   openapi: "3.0.0"
   info:
     version: 1.0.0
     title: Swagger Petstore
   paths:
     /pets:
       # POST operations are 'write' by default, but this can be overridden
       post:
         x-taxi-operation-kind: read  # Override to make a POST operation read-only
         responses:
           '200':
             description: successful operation
             content:
               application/json:
                 schema:
                   type: object
                   properties:
                     name:
                       type: string
       
       # GET operations are 'read' by default, but this can be overridden
       get:
         x-taxi-operation-kind: write  # Override to make a GET operation a write operation
         responses:
           '200':
             description: successful operation
             content:
               application/json:
                 schema:
                   type: object
                   properties:
                     name:
                       type: string

Possible values for x-taxi-operation-kind:

  • read - The operation is read-only (default for GET, HEAD, OPTIONS)
  • write - The operation modifies data (default for POST, PUT, PATCH, DELETE)

​
Enriching OpenAPI Components

​
Response Models

Add semantic meaning to response types:

components:
  schemas:
    Customer:
      x-taxi-type:
        name: acme.Customer
      properties:
        id: 
          type: string
          x-taxi-type:
            name: acme.CustomerId
        email:
          type: string
          x-taxi-type:
            name: acme.EmailAddress

​
Input Parameters

Enrich API parameters with semantic types:

paths:
  /customers/{id}:
    get:
      parameters:
        - name: id
          in: path
          schema:
            type: string
            x-taxi-type:
              name: acme.CustomerId

​
Field Attributes

Add semantic meaning to model fields:

components:
  schemas:
    Customer:
      properties:
        name:
          type: string
          x-taxi-type:
            name: acme.CustomerName
            # Only create if type doesn't exist
            create: true
Previous
Overview
Next
Avro