RESTful API Modeling Language (RAML)

The easiest way to design reusable APIs.

The steadily increasing share of web applications is based on the increasing networking between customers and companies. The interaction of the participants is regulated by APIs, which digitally connect the apps and the IT infrastructure. For this reason, it is particularly important that an API is kept as flexible and transparent as possible for its users. Even design errors in the project planning phase can be found and corrected quickly and safely with a well-structured documentation. Especially projects with an API first approach are often subject to a change process, which makes a complete representation of the interfaces and parameters indispensable.

RAML (RESTful API Modeling Language) is a descriptive language designed specifically for API First and RESTful API modeling. The goal here is above all the complete provision of all information for the description and generation of an API. Defined by MuleSoft as a specification in 2013, RAML is today in the current version 1 with the release date 2017-07-06. The notation of the API is done in YAML 1.2 format. As language support Java, Node.js, Mule, Phyton and IOT are offered. In addition to the founder MuleSoft, the RAML specification is also supported by Cisco, VMWare, .Net, PayPal, SOA Software, Kin Lane and AngularJS.

API core elements in RAML

The most detailed and complete documentation of an API is particularly important in terms of usability and maintenance. In terms of content, all important parameters, business objects, error codes and additional information must be described exactly and ideally also with short examples. The core elements shown below should therefore be present in every API description and presented as detailed as possible. We describe the different areas with a fictional example of an airline in which different actions such as bookings, cancellations or requests for information are to be made.

Docs

For the most detailed description of the API components, corresponding documents can be named in the section docs. A user manual can also be integrated here in the form of links and includes. For this, the two parameters documentation: and title: are available to describe a reference link. It is also a multiple naming of links and descriptions possible. The following source text snippet shows an example:

documentation:
  - title: Home
    content: |
      Welcome to the airline Fly Away. We are an european low cost airline. You can find the cheapest airline fares within Europe.
  - title: Languages
    content: |
      Please select a language of your choice for our airline API. We offer the following languages: English, German, Spanish, French and Italian. See our library [languages libraries](http://www.google.com).

Details

Basic information about the full API is noted in the Details section. For this purpose, various parameters such as info:, title: or servers: are available. In the following source text excerpt you can see an example of our fictitious airline:

title: Airline Fly Away API
version: v1
baseUri: http://api.dataliquid.com/airline/{version}
description: This API allows to interact with our airline Fly Away API.
mediaType: application/json

The title: parameter should describe the basic functionality of the API. The version specification in the version: parameter is of interest to revision control. The baseUri: parameter specifies the path to the API, which may include a versioning level. In description: you give more information about the API. Under mediaType: you list the format language used for the API.

Security

In this section, all safety information is noted. Usually the authentication methods used in the API are listed here. The security level and other parameters are defined via various specifications. The following source text section describes the authentication settings for our fictitious company:

securedBy: [oauth_2_0]
securitySchemes:
  oauth_2_0:
    type: OAuth 2.0
    displayName: OAuth 2.0
    description: |
      This API supports OAuth 2.0. The necessary `ClientId` and `ClientSecret` will be supplied by the _provider_ of the API. `Access-Tokens` will be issued by means of Id and Secret and are subjected to `TimeToLive`, short TTL, that is provided when the token is issued. Expired Tokens are rejected by the API with the HTTP Status `403`.
    describedBy:
      headers:
        Authorization:
          type: string
          displayName: Authorization
          description: |
            Used to send a valid OAuth 2 access token. Do not use with the "access_token" query string parameter.
          example: Bearer MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3
      queryParameters:
        access_token:
          type: string
          displayName: Access Token
          description: |
            Used to send a valid OAuth 2 access token. Do not use with the "Authorization" header.
          example: MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3
      responses:

The first parameter securedBy: defines the authentication method to be used, which is valid as root over the whole API. This is followed by one or more definitions with a set of parameters such as type:, displayName:, describedBy: and queryParameter:. With these details the used authorization procedure is described in detail. This is followed by information on the access token access_token: and the possible response codes responses:.

Resources

To define the access to the different resources via the API, different access methods are used in the HTTP protocol. As a rule, the four most common method calls come into question here. These signal to the browser how to handle a request and how to use the parameters it carries. The following list briefly introduces the four method calls:

GET - The GET method can be used, for example, to read a resource without changing the inventory data. For our fictitious airline, this call would correspond to a query about a particular flight.

POST - The POST method is intended to create a new resource. The resource to be generated must not yet exist in the system. In our example, this method call corresponds to the creation of a new customer booking for a flight.

PUT - You can use this method to change or complement a resource that already exists in the system. A change to the flight data, such as the departure time, in an existing booking would be a corresponding example.

DELETE - If a resource is no longer needed in the system, you can use this method call to delete it. This would be the case if a customer wants to delete a booking record that has already been saved.

In the API, the corresponding parameters are listed in detail for each method call. Using our airline as an example, a visitor searches our website for suitable flights using the search parameters (queryParameters). In the following source text you will find an excerpt of the exemplary definition of the GET method:

/flights:
  get:
    displayName: Search flights
    description: Customer searches for flights by using different filters.
    queryParameters:
      departure_airport:
        type: string
        displayName: Departure airport
        description: Departure airport according to the IATA airport code. It's a threeletter
        code designating many airports around the world.
        example: "BER"
        required: false
      destination_airport:
        type: string
        displayName: Destination airport
        description: Destination airport according to the IATA airport code. It's a
        three-letter code designating many airports around the world.
        example: "LON"
        required: false
      flight_type:
        type: string
        displayName: Flight type
        description: Flight is either one way or return.
        example: "One way"
        required: false
      outgoing_flight_date:
        type: date-only
        displayName: Outgoing flight date
        description: The date of the outbound flight.
        example: "2018-12-11"
        required: false
      return_flight_date:
        type: date-only
        displayName: Return flight date
        description: The date of the return flight.
        example: "2018-12-18"
        required: false
      passengers:
        type: number
        displayName: Passengers
        description: Number of flight passengers.
        example: 1
        required: false
    responses:

Types

An essential part of the API definition is the detailed representation of the business objects used with all required parameters. Here we also find the object properties like departure_airport:, destination_airport: or price: One of these object types for the flight search (FlightSearchType) we will briefly introduce in the following source code excerpt:

types:
  FlightSearchType:
    type: object
    displayName: Flight search type
    description: User searches for flights and receives information about available flights, date and time, flight number.
    properties:
      departure_airport:
        type: string
        displayName: Departure airport
        description: Departure airport according to the IATA airport code. It's a three-letter code designating many airports around the world.
        example: "BER"
      destination_airport:
        type: string
        displayName: Destination airport
        description: Destination airport according to the IATA airport code. It's a three-letter code designating many airports around the world.
        example: "LON"
      price:
        type: PriceType
        displayName: Price
        description: Price of the flight.
        example:
      price: 79.99
      currency: "EUR"

Errors

Another important section in the API definition are the communication status messages. These should be listed in as much detail as possible in order to be able to carry out a possible troubleshooting or user message effectively. An error message is returned in JSON format, as the following source code excerpt shows:

responses:
  404:
    body:
      application/json:
        type: ErrorType
        example: |
          {
          "reason": "RESOURCE_NOT_FOUND",
          "message": "Resource not found",
          "trace_id": "550e8400-e29b-11d4-a716-446655440000"
          }

Advantages and disadvantages of RAML

Compared to other markup languages such as Open API, RAML offers a simple and convenient way to integrate recurring source code and schemas. There is also an active community that provides excellent support and code snippets. With professional tools like the Atom Plugin API Workbench or the Mule Studio a fast and comfortable project planning is possible. A disadvantage here are the few available tutorials that could make it easier for a newcomer to get started. Another problem is the lack of downward compatibility of the different versions as well as the relatively small number of languages compared to other description languages.

Conclusion

If you basically need fast and clean designs for RESTful API’s, the RAML description language is currently a clear advantage. Especially with regard to agile API-First projects, the documentation should be kept as simple but transparent as possible. Due to the flexible reusability of objects and code fragments, RAML can clearly score against the competition. With RAML, the integration of XML schemata is completed in seconds. In particular, the API Workbench is very easy and intuitive to use. Nevertheless, it should be noted that due to new developments and advancing standards, the Open API markup language is gaining considerable popularity and will probably be defined as a new standard in the foreseeable future.