Last Updated on 22/02/2019 by Patryk Bandurski
This article is an intro into a blog series about HTTP methods usage in RESTful services. As a GET is the most common I will start with it. This method is used for retrieving collection of resources or a single resource. In other words this could be used for searching purposes. However the more advanced search criteria I will describe in next article.
To design a service I will use two most commonly used specifications such as RAML and OpenAPI.
Tools
I am going to use following tools:
- Anypoint Platform for service design
- Swagger for service design using OpenAPI specification
Use Case
Let’s imagine that we are responsible for a design of a completely new service. This service should allow client to manage accounts of a domain system. All data are stored within NoSQL database – this is just an implementation details that do not change our design. By manage I think about listing all available accounts , finding a particular one by id or searching by a given constraint. As you may expect the primary resource would be an account.
In our scenario account has only following parameters:
- login of type string
- name of type string
- surname of type string
- role of type string
- email of type string but not mandatory
- rank of type integer
Service Design
Get list of resources
One of the most obvious scenario would be to get all possible resources. For given resource we set url with pluralized noun
/accounts
Of course they are some exceptions to this rule. When we have a resource that we know that only one entry exists we may use singular noun. It depends from the project’s domain perspective. Let’s say I would like to publish configuration resource. This resource stores global config. In other words only one exists. So I would set following url:
/configuration
On the other hand when we have compound nouns like LDAP account, DB account or Email account we should not make compound resource name like /ldapaccounts. It is easier to read and maintain situation where we split nouns by slash in URL like the following examples:
/ldap/accounts /db/accounts /email/accounts
When we hit url like /accounts we may encounter two different situations. First is an empty response like below
[ ]
and the second one is an array of resources:
[{ "login": "aabacki", "name": "a", "surname": "abacki", "role": "ADMIN", "rank": 20 }]
In both cases http status 200 should be returned.
Get single resource by id
Previous operation allowed to get all available resources. How about getting a particular one? For each record unique id should be selected. By this id we will search the list. We need to append id after slash like bellow
/resource/{id} /accounts/aabacki /applications/872233
First example mean that we would like to get account which id is equal to aabacki and the second one application identified by 872233.
Encoding characters
In given example id contains characters but it can contains digits, and special characters like spaces. When special characters occurs we need to encode given URI. Here are a couple of examples.
/accounts/12345 ⇒ /accounts/12345 /accounts/123 45 ⇒ /accounts/123%2045 /accounts/mail@domain.pl ⇒ /accounts/mail%40domain.pl
In first example nothing was changed. However in second and third some changes occurred. Space was replaced with %20 and @ character with %40.
When we try to get such resource we should receive its content with http status 200 like below:
{ "login": "aabacki", "name": "a", "surname": "abacki", "role": "ADMIN", "rank": 20 }
A key difference here is that we received a single object within curly bracket. No like in the previous call, array of objects.
When the id is not known we should receive an empty body with http status 404.
Get resource(s) by field
There are some situations where we do not know unique identifier, however we do know other attributes. We can solve this problem in two ways by either query or uri parameters.
Searching by query parameters
We may search by any field we would like to, although there are some limitations. We need to decide by which fields our resource should be queried. For an account I have decided to query by surname, role and rank field. So how does do URL looks like?
/accounts?surname=Abacki&role=ADMIN
So let’s break this structure down. This URI contains:
- resource name like accounts
- question mark that separate query parameters with name of the resource
- query parameter
- name of the parameter like surname
- equals character =
- value to compare
Query parameter should appear at least once after the question mark. In the given example we have two query parameters surname and role.
Searching by uri parameters
URI parameters are hidden within address. Following address /accounts/2017/admin may return accounts created in 2017 that belonged to administrators. However the search parameters are not optional in comparison to query parameters and must follow in that exact order.
Headers
The majority of RESTful services will return JSON content. However the JSON content is not the only one representation that REST service can return. It may be as well XML or any other. What is more service can accept more the one representation. In other words it can return JSON and XML content for example.
How do we inform service that we would like specific representation? We do this by specifying Accept header.
Accept: application/json Accept: application/xml
When you do not specify this header you will receive default service representation.
Design
As we have some basic idea about GET method, we are ready to design simple service using both RAML and Open API specification. I will design simple service using Anypoint Platform and Swagger.
We need to perform following actions:
- create reusable definition of our entity – account
- create get /accounts operation
- add optional query parameters to get /accounts operation
- create get /accounts by login operation
Anypoint Platform
If you do not have an account you can create one, free of charge, under following link. After that we login an and clicking Design button under Design Center header.

In the following screen we add new API specification in my case it is accounts-service. We should be welcomed with editor where we will design our service. Screen is dived into three sections:
- File’s explorer
- Design canvas in the middle
- API console – displaying in a user friendly manner our API

Resource definition
As a default we got information that we are going to design using RAML specification in version 1.0. First we need to specify our reusable type. Here is the code that should be added:
#%RAML 1.0 title: accounts-service types: account: type: object properties: login: name: surname: role: email?: rank: type: integer default: 0
We defined type under types keyword by name (line 4). Next we specified what kind of type we are defining by setting property type. In line 6 we set it to object. This means that our account will contain properties. Since it is an object we define properties in properties property. From lines 8 to 12 we do not specify anything except property name. This is a shortcut for defining string property. We could define each property in the following manner:
properties: login: type: string
Line 12 depict how to mark that property is optional.
Get the list of accounts
It is time to define first operation which is get list of accounts. But wait a moment. We defined just an object account not an array of objects. In RAML version 1.0 we are able to reuse object definition for creating an array. It will become clear in next paragraph.
First we will define simple get /accounts just like blow:
/accounts: get: responses: 200: body: application/json: type: array items: type: account application/xml: type: array items: type: account 415: description: Unsupported Media Type
As you may see we start with our resource name and in the next line we define which verb is available under this resource. While get does not have request body we need to define response in responses property(line 19). I have defined two different http status codes for response in line 20 and 30. We will return either 200 which mean everything went ok or 415 when client will try to get our resource using unsupported media type. For each return status we need to specify what its body will contain. Our service will return either json or xml response (line 22 and 26). For each returned response we need to specify what it will contain. For both response’s format we return array (line 23). Each item within array is of type account (line 25).
So far we got following defition and when we hit /accounts endpoint we should be able recive an array of accounts. Here is an example of possible outcome:

Simple accounts’ filter
It is time to add some basic filters. We need to add queryParamters section under our resource like in line 19. As with type definition we need to define what parameters are available like name, type and if it is mandatory or not.
/accounts: get: queryParameters: surname?: role?: rank?: type: integer responses: 200:
Getting specific resource
The last operation but not least is getting account by login. We have basic get /accounts (defined in line 17, 18). Next we need to define a placeholder for login. In order to do it we enclose placeholder with curly brackets like in line 20. The reason why we used placeholder is fact that this part of URI will change. After that line, we perform similar steps as with get /accounts. We define possible body’s types like json or xml. Line 26 show that service will return single account by specifying type to be account.
/accounts: get: ... /{login}: get: responses: 200: body: application/json: type: account application/xml: type: account
Here is an example of the URI and possible response:
Swagger
If you do not have an account you can create one, free of charge, under following link. After that we login and we should see list of all defined services.

In order to create new API click create new API. In the popup screen we may fill just API name. Canvas is divided into two sections:
- Design canvas
- User friendly API graphical representation
Resource definition
In first four lines we define basic information about our service like:
- swagger version
- version of our AP1
- title of our API
First we need to specify our reusable type. Here is the code that should be added:
swagger: '2.0' info: version: 1.0.0 title: accounts-service definitions: Account: type: object properties: login: type: string surname: type: string name: type: string role: type: string email: type: string rank: type: integer default: 0 required: - login - surname - name - role - rank
All types are described within definitions property. We defined new account type in types (line 7). Next we specified that account is an object (line 8). This means that our account will contain properties. We define them after keyword properties in line 9. From lines 10 to 22 we define properties’ names and their types. After the keyword required (line 23) we mark which properties should be mandatory. required keyword holds an array of values. In YAML language array’s item is preceded with hyphen character.
JSON Schema
JSON Schema describes JSON types and validate them. As JSON is JavaScript Object Notation JSON Schema is defined using JavaScript language as well. Those of you who are familiar with JSON Schema should notice some similarity with OpenAPI specification. Definition from above is equivalent of the following schema file:
"definitions": { "account": { "type": "object", "properties": { ... }, "required": [...] } }
Get the list of accounts
It is time to define first operation which is getting the list of accounts.
First we will define simple get /accounts just like blow:
paths: /accounts: get: produces: - application/json - application/xml responses: 200: description: Accounts list schema: type: array items: $ref: '#/definitions/Account'
All paths we define under paths property. As you may see we start with our resource name and in the next line we define which verb is available under this resource. Our service will return either json or xml response (line 33, 34). This is defined in produces array. While get does not have request body we need to define response (line 35). We will return 200 which means everything went ok. For each returned response we need to specify what it will contain. For both response’s format we return type array (line 39). Each item within array is of type account (line 41). This notation is used in JSON Schema. $ref is used to made a reference to known element within schema. I will break this url down:
- #/ means that we would like to search current file,
- definitions made us to look at properties under definitions property,
- and there finally Account.
So far we got definition and when we hit /accounts endpoint we should be able receive an array of accounts.
Simple accounts’ filter
It is time to add some basic filters. In order to do in we need to add parameters (line 35). Parameters is an array of objects. Each item of this array contains:
- in specifying if item is a query or URI parameter
- name specifying name of the parameter
- description
- required specifying if parameter is mandatory or not
- type like integer or string
Base on this description you should conclude that parameters are just query parameters of name surname, role and rank and all are optional.
produces: - application/json - application/xml parameters: - in: query name: surname required: false type: string - in: query name: role required: false type: string - in: query name: rank required: false type: integer responses:
Getting specific resource
The last operation but not least is getting account by login. We need to define a placeholder for login. In order to do it we enclose placeholder with curly brackets like in line 55. The reason why we used placeholder is fact that this part of URI will change. As URI parameter is used we need to define it within parameters array in line 60. Bare in mind that this parameters should be marked as mandatory (line 63). Line 69 depicts that service will return single account by specifying type to be account.
/accounts/{login}: get: produces: - application/json - application/xml parameters: - in: path name: login required: true type: string responses: 200: description: Account schema: $ref: '#/definitions/Account'
Summary
- GET is used for retreiving resources
- Resources are available under pluralized noun URI like /accounts
- Filtering is possible by using either query or URI parameters
- RAML specification is concise form describing the service in YAML language
- OpenAPI specification is more JSONSchema like in YAML language
Specifications
Service’s specifications are available at github.