Specification


Table of Contents


Introduction

The TypeAPI specification defines a JSON format to describe REST APIs for type-safe code generation.

Goals

Non-Goals

Reasoning

For a long time the OpenAPI community was divided into two communities, one building documentation tools and the other trying to build code generation tools. Building documentation tools has very different requirements than building code generation tools. For a documentation tool you can simply render and show all defined endpoints and constraints, a code generation tool on the other side needs to understand the structure and relations of your model.

The OpenAPI specification has moved more and more to the documentation community by directly integrating JSON Schema into the specification. The problem with JSON Schema and code generation is, that JSON Schema is a constraint system, based on such constraints it is very difficult or impossible to build a clean code generator since the constraints only define what is not allowed. For a code generator you like to have a schema which explicit models your data structure.

With TypeAPI we want build a new home for the code generation community. Conceptual the main difference is that with OpenAPI you describe routes and all aspects of a route, at TypeAPI we describe operations, an operation has arguments and those arguments are mapped to values from the HTTP request. Every operation returns a response and can throw exceptions which are also mapped to a HTTP response. An operation basically represents a method or function in a programming language. This approach makes it really easy to generate complete type safe code.


Root

Every TypeAPI has a Root definition. The Root must contain at least the operations and definitions keyword i.e.:

{
    "operations": {
        "com.acme.api.hello.getMessage": { ... },
    },
    "definitions": {
        "TypeA": { ... },
        "TypeB": { ... }
    }
}

Operations

The operations keyword contains a map containing Operation objects. The key represents the global identifier of this operation. In general we recommend to use as prefix for every operation key the reverse name of your domain (i.e. com.acme.api.myOperation) which makes it globally unique. The generated client code always uses the last part of your operation key as method name.

{
    "operations": {
        "com.acme.api.hello.getMessage": {
            "description": "Returns a hello world message",
            "method": "GET",
            "path": "/hello/world",
            "return": {
                "schema": {
                    "$ref": "Hello_World"
                }
            }
        }
    },
    "definitions": {
        "Hello_World": {
            "type": "object",
            "properties": {
                "message": {
                    "type": "string"
                }
            }
        }
    }
}

Return

Every operation can define a return type. In the above example the operation simply returns a Hello_World object.


Arguments

Through arguments you can map values from the HTTP request to specific arguments. In the following example we have an argument status which maps to a query parameter and an argument payload which contains the request payload.

{
    "operations": {
        "com.acme.api.hello.insertMessage": {
            "description": "Inserts and returns a hello world message",
            "method": "POST",
            "path": "/hello/world",
            "arguments": {
                "status": {
                    "in": "query",
                    "schema": {
                        "type": "integer"
                    }
                },
                "payload": {
                    "in": "body",
                    "schema": {
                        "$ref": "Hello_World"
                    }
                }
            },
            "return": {
                "schema": {
                    "$ref": "Hello_World"
                }
            }
        }
    },
    "definitions": {
        "Hello_World": {
            "type": "object",
            "properties": {
                "message": {
                    "type": "string"
                }
            }
        }
    }
}

This would map to the following HTTP request.

POST https://api.acme.com/hello/world?status=2
Content-Type: application/json

{
  "message": "Hello"
}

Throws

Besides the return type an operation can return multiple exceptional states in case an error occurred. Every exceptional state is then mapped to a specific status code i.e. 404 or 500. The generated client SDK will then throw a fitting exception containing the JSON payload in case the server returns such an error response code. The client will either return the success response or throw an exception. This greatly simplifies error handling at your client code.

{
    "operations": {
        "com.acme.api.hello.getMessage": {
            "description": "Returns a hello world message",
            "method": "POST",
            "path": "/hello/world",
            "return": {
                "schema": {
                    "$ref": "Hello_World"
                }
            },
            "throws": [{
                "code": 404,
                "schema": {
                    "$ref": "Error"
                }
            }, {
                "code": 500,
                "schema": {
                    "$ref": "Error"
                }
            }]
        }
    },
    "definitions": {
        "Hello_World": {
            "type": "object",
            "properties": {
                "message": {
                    "type": "string"
                }
            }
        },
        "Error": {
            "type": "object",
            "properties": {
                "message": {
                    "type": "string"
                }
            }
        }
    }
}

Definitions

The definitions keyword maps to the TypeSchema specification and represents a map containing Struct, Map and Reference types. Those types are then used to describe incoming and outgoing JSON payloads.


Appendix

The single source of truth of TypeAPI is the TypeSchema meta schema which describes the TypeAPI specification. You can find the current TypeSchema at our repository. The following section contains a HTML representation which we automatically generate from this schema.

Argument

{
  "in": String,
  "schema": typeschema:BooleanType | typeschema:NumberType | typeschema:IntegerType | typeschema:StringType | typeschema:ReferenceType,
}
FieldDescription
inString
The location where the value can be found either in the path, query, header or body. If you choose path, then your path must have a fitting variable path fragment
Enum
  • "path"
  • "query"
  • "header"
  • "body"
schematypeschema:BooleanType | typeschema:NumberType | typeschema:IntegerType | typeschema:StringType | typeschema:ReferenceType

Arguments

Contains a map of arguments. The key will be used as variable name at the generated code so it is recommended to use only a-z and underscore as characters
Map (Argument)

Operation

{
  "method": String,
  "path": String,
  "return": Return,
  "arguments": Arguments,
  "throws": Array (Throw),
  "description": String,
  "stability": Integer,
  "security": Array (String),
  "authorization": Boolean,
  "tags": Array (String),
}
FieldDescription
methodString
The HTTP method which is associated with this operation, must be a valid HTTP method i.e. GET, POST, PUT etc.
pathString
The HTTP path which is associated with this operation. A path can also include variable path fragments i.e. /my/path/:year then you can map the variable year path fragment to a specific argument
returnReturn
The return type of this operation. The return has also an assigned HTTP success status code which is by default 200
argumentsArguments
All arguments provided to this operation. Each argument is mapped to a location from the HTTP request
throwsArray (Throw)
All exceptional states which can occur in case the operation fails. Each exception is also assigned to an HTTP error status code
descriptionString
A short description of this operation. The generated code will include this description at the method so it is recommend to use simple alphanumeric characters and no new lines
stabilityInteger
Indicates the stability of this operation. This is based on the stability index from the nodejs project: 0 - Deprecated, 1 - Experimental, 2 - Stable, 3 - Legacy. If not explicit provided the operation is by default experimental.
Enum
  • 0
  • 1
  • 2
  • 3
securityArray (String)
An array of scopes which are required to access this operation
authorizationBoolean
Indicates whether this operation needs authorization, if set to false the client will not send an authorization header, default it is true
tagsArray (String)
Optional an array of tags to group operations. Those tags are used at the client generator to group operations

Operations

A map of operations which are provided by the API. The key of the operation should be a global unique string separated by a dot, we recommend to use the java package naming convention and use your domain reversed as prefix before every operation name
Map (Operation)

Return

{
  "code": Integer,
  "schema": typeschema:ReferenceType,
}
FieldDescription
codeInteger
The associated HTTP response code
schematypeschema:ReferenceType

Security

{
  "type": String,
}
FieldDescription
typeString
Enum
  • "httpBasic"
  • "httpBearer"
  • "apiKey"
  • "oauth2"

SecurityApiKey extends Security

Describes that the API requires an Api-Key authentication, the user needs to provide a token and the client will place this token at the describes header or query parameter
{
  "name": String,
  "in": String,
}
FieldDescription
nameString
inString

SecurityHttpBasic extends Security

Describes that the API requires an HTTP Basic authentication, the user needs to provide a username and password at the client
{
}
FieldDescription

SecurityHttpBearer extends Security

Describes that the API requires an HTTP Bearer authentication, the user needs to provide an access token, how the user obtains this access token is out-of-bound of this specification
{
}
FieldDescription

SecurityOAuth extends Security

Describes that the API requires an OAuth2 authentication, the user needs to provide a client id and secret, then the client tries to automatically obtain an access token using the client credentials grant
{
  "tokenUrl": String,
  "authorizationUrl": String,
  "scopes": Array (String),
}
FieldDescription
tokenUrlString
authorizationUrlString
scopesArray (String)

Throw

{
  "code": Integer,
  "schema": typeschema:ReferenceType,
}
FieldDescription
codeInteger
The associated HTTP response code
schematypeschema:ReferenceType

TypeApi

The root TypeApi
{
  "$import": typeschema:Import,
  "baseUrl": String,
  "security": SecurityHttpBasic | SecurityHttpBearer | SecurityApiKey | SecurityOAuth2,
  "operations": Operations,
  "definitions": typeschema:Definitions,
}
FieldDescription
$importtypeschema:Import
baseUrlString
Optional the base url of the service, if provided the user does not need to provide a base url for your client
securitySecurityHttpBasic | SecurityHttpBearer | SecurityApiKey | SecurityOAuth2
operationsOperations
definitionstypeschema:Definitions
Edit this page