Skip to main content

Introduction to RAPID Schema Definition Language (RSDL)

RAPID Schema Definition Language (RSDL) is a language to define Web APIs.

RSDL is based on the RAPID Profile of the OData specification. RAPID provides an easy way to envision, create, and consume a Web API that is compatible with the OData Standard and can evolve over time to support more advanced scenarios.

Introductory Example​

RAPID APIs are defined by a schema, which can easily be specified using RSDL.

Defining a Structured Type​

Let's say that we wanted our API to deal with information about a company. We could specify the properties of a company as follows:

type Company
{
stockSymbol: String
name: String
incorporated: Date
}

Our company has three properties: a stockSymbol, a name, and the date of incorporation.

A property in RAPID can be an Integer, String, Boolean, DateTime, Date, Double, Decimal, TimeOfDay, Duration built-in types, an enum type, a structured type, or a collection of any of the former.

Defining a Service​

Now we can create a service that returns information about our company:

service {
company: Company
}

This allows us to make simple requests against our company:

RequestComment
GET http://rapid-pro.org/company?select=stockSymbol,nameget the stock symbol and name of the company
PATCH http://rapid-pro.org/company
{ "name":"Spacely's Space Sprockets" }
update the company name

Defining a Structured Type Property​

Now let's say that we wanted to add employees to our company.

First, we would define the employee type:

type Employee
{
key id: Integer
firstName : String
lastName : String
title: String
}

The id property is identified as a key, meaning that instances of employees within a collection can be referenced by their id.

Now we can add employees to our company:

type Company
{
stockSymbol: String
name: String
incorporated: Date
employees: [Employee]
}

The employees property is a collection of our employee type. Because it is a collection, the type is enclosed in square brackets [...].

Now we can get employees for our company:

RequestComment
GET http://rapid-pro.org/company/employees?select=lastName,titlelist the last name and title for all employees for the company
GET http://rapid-pro.org/company/employees/1?select=lastName,titleget the last name and title of the employee with id=1
GET http://rapid-pro.org/company?select=name&expand=employees(select=lastName)get the company name and the last names of all of its employees
POST http://rapid-pro.org/company/employees
{ "firstName": "Cosmo","lastName": "Spacely","title": "CEO" }
add a new employee
PATCH http://rapid-pro.org/company/employees/1 {"title": "Assistant to the Assistant Regional Manager"}change the title of the employee with id=1
DELETE http://rapid-pro.org/company/employees/1delete the employee with id=1

Defining a Top-Level Collection​

Our service exposes a single top-level company instance.

We could also add a top-level collection.

For example, we could reuse the same company type to create a collection of companies that are competitors.

service {
company: Company
competitors: [Company]
}

Because company is now part of a collection, if we want to reference individual companies within the collection we would define a key. In this case, we use stockSymbol as the key:

type Company
{
key stockSymbol: String
name: String
incorporated: Date
employees: [Employee]
}

Now we can request individual companies within the competitors collection:

RequestComment
POST http://rapid-pro.org/competitors
{ "stockSymbol":"cgswl", "name":"Cogswell's Cosmic COGs" "incorporated":"2054-10-04T00:00:00Z" }
create a new competitor
GET http://rapid-pro.org/competitors?select=namelist the names of all of the competitors
GET http://rapid-pro.org/competitors/cgswl?select=nameget the name of the competitor with the stock symbol cgswl
GET http://rapid-pro.org/competitors/cgswl/employees?select=lastNameget the last name of employees for the competitor with the stock symbol cgswl
DELETE http://rapid-pro.org/competitors/cgswldelete the competitor with the stock symbol cgswl

Defining an Enum​

Enumerations allow us to define a string-valued property with a fixed set of values.

Let's say that we wanted to define an employmentType enumeration, with possible values "salaried" and "hourly". We could do so as follows:

enum EmploymentType
{
salaried
hourly
}

Now we could use that employmentType enum in our employees example:

type Employee
{
key id: Integer
firstName: String
lastName: String
title: String
employeeType: EmploymentType
}

Defining a Structured Property without Identity​

Our employee has first name and last name properties. We could define a "fullName" type to group those properties together:

type FullName
{
firstName: String
lastName: String
}

and then use that type in our employee:

type Employee
{
key id: Integer
name: FullName
title: String
}

Grouping these properties together keeps them organized and makes them easy to use in various structured types.

Defining Methods​

RAPID supports actions and functions.

Actions​

An action takes zero or more input parameters and may or may not return a value. Actions may have side effects.

We can define a "youAreFired" action on our company that takes a string parameter "reason":

type Company
{
key stockSymbol: String
name: String
incorporated: Date
employees: [Employee]
topEmployees(num: Integer): [Employee]
action youAreFired(reason: String)
}

youreFired has the action attribute to show that it is an action and may have side-affects. It does not return a value.

Because actions may have side-affects, they are invoked using POST. Their parameters are passed in the body of the request.

RequestComment
POST http://rapid-pro.org/company/employees/1/youreFired
{ "reason": "Embezzlement" }
invoke the youreFired action on employee with id = 1

Actions and functions may also be defined on the service.

service {
company: Company
competitors: [Company]
currentStockPrice(stockSymbol: String): Decimal
}
RequestComment
GET http://rapid-pro.org/currentStockPrice?stockSymbol=cgswlget the current stock price for cgswl

Functions​

A function takes zero or more input parameters, and returns a value. Functions must not have side effects.

We can define a "topEmployees" function on our company:

type Company
{
key stockSymbol: String
name: String
incorporated: Date
employees: [Employee]
topEmployees(num: Integer) : [Employee]
}

topEmployees takes a single Integer parameter "num" and returns a collection of employees.

Functions are invoked using a GET request. Function parameters are passed in the URL.

RequestComment
GET http://rapid-pro.org/company/topEmployees?num=10get the company's top 10 employees