Getting started

Requests

Our API is a collection of 'RESTful' web services. You interact with our resources by sending an HTTP message to a URL. The URL determines the resource and the HTTP method defines the type of action.

Authentication

All requests must include an Authorization header with a valid access_token. See Security for more details on access_tokens.

HTTP Methods

These are the methods our apis support. Not all methods are implemented for all resources.

We prefere the use of PATCH over PUT, so the PUT is rarely used in our endpoints.
Method Description

GET

Get a resource

PUT

Replace a resource

POST

Add a resource

DELETE

Delete a resource

PATCH

Update properties on a resource

Request structure

Requests to our APIs have the following structure:

https://<host>/<api-version>/<domain>/(<resource/\{id\})*>?(query-parameters)
Example (Post Request)
POST  https://<host>/v1/surveys/p1231234/respondents HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "email": "test@forsta.com",
  "city": "oslo",
  "country": "norway"
}

Request Headers

Name Syntax Description Example

Accept

Accept: <MIME-type>/*
Accept: <MIME-type>/<MIME-subtype>
Accept: */*

Indicates which MIME types the client is capable of understanding. During content negotiation, the server should select which of the MIME types for the response. That choice is communicated back to the client using the Content-Type response header.

Accept: application/json

Authorization

Authorization: <type> <credentials>

Specifies the credentials of the client to authenticate with a service. All services must support the Authorization header.

Authorization: Bearer c1das334aff

If-Match

If-Match: <etag_value>
If-Match: <etag_value>, <etag_value>, …​

Specifies a conditional request to only return the resource when it does match one of the included ETag values. All services must support the If-Match header provided they support the ETag response header.

If-Match: ID-123123

If-None-Match

If-None-Match: <etag_value>
If-None-Match: <etag_value>, <etag_value>, …​

Specifies a conditional request to only return the resource when it doesn’t match one of the included ETag values. All services must support the If-None-Match header provided they support the ETag response header.

If-None-Match: ID-123123

Paging

You can control the number of items returned when requesting a resource collection by using the query parameters below. We call the collection of items returned a "page".

Parameter Type Description Example

pageSize

Integer

The number of items per "page". If not specified, 100 items will be returned.

GET  https://...?pageSize=50

page

Integer

The index of the "page" to return. If not specifed, the first "page" will be returned.

GET  https://...?page=2
Returns the second page of 100 items, numbered 101-200.

GET  https://...?pageSize=30&page=1
Returns the first page of 30 items, numbered 1-30.

GET  https://...?pageSize=30&page=4
Returns the fourth page of 30 items, numbered 91-120.

Responses

An HTTP Response is what you get when you make an HTTP Request.
There are two important properties of a response that you should care about:

  • HTTP Status Code - this tells you at a protocol level what the status of the response is

  • Response Payload - this is the body of the response. It is in a standard format that will give you the application level status, the results, and if applicable, any errors.

Response Formats

All responses are returned using JSON. JSON is a lightweight serialization language that is compatible with many different languages. JSON is syntactically correct JavaScript code, meaning you can use the Javascript eval() function to parse it.

Response Payload

We comply with HATEOAS, or Hypermedia As The Engine Of Application State. This means that our Rest APIs are accessible through the use of hypermedia links, and that all resources returned by our APIs contains a "links" property.

Example (Single resource payload)
{
  "id": 15,
  "name": "John Doe",
  "links": {
    "self": "/resource/15",
    "sub-resource": "/resource/15/sub-resource"
  }
}
Example (Resource collection payload)
{
  "itemCount": 100,
  "totalCount": 23533,
  "items": [
  {
    "id": 14,
    "name": "test1"},
  {
    "id": 16,
    "name": "test2"}
  ],
  "links": {
    "item": "/resource/{id}", (1)
    "self": "/resource?pageSize=100&page=1",
    "next": "/resource?pageSize=100&page=2",
  }
}
1 The item-link is used to get the link to an individual item in the collection. The {id} parameter is replaced with the "id"-property on the item itself.

HTTP Status Codes

Our REST APIs use standard HTTP status codes to indicate success or failure of API calls. Below are the most common codes our APIs support. To learn more about Status Codes, see Wikipedia.

HTTP Status Code Message Description

200

OK

The request was processed and returned successfully. Nothing was changed.

201

Created

The new resource was created successfully

400

Bad Request

Problem with the request, such as a missing, invalid or type mismatched parameter

401

Unauthorized

The request did not have valid authorization credentials

403

Forbidden

Private data you are not allowed to access, or you’ve hit a rate limit.

404

Not Found

Your URL is wrong, or the requested resource doesn’t exist

500

Server Error

Internal server error. If this persists, please contact support.

503

Service Unavailable

Our API is down. Please try again later.

Dates and Times

We support the ISO 8601 format for passing in dates and times. This allows for a very flexible array of options, allowing you to pass in the level of detail you need to.

The full representation of a date and time is of the format:

yyyy-MM-ddTHH:mm:ss.SSSZ

Date and time values generated by our APIs will be relative to the location of the API Web Server.
If the server is located in Paris, France, a resource with a "CreatedDate" property populated by the server would be returned by the server as the example below.
The +01:00 suffix to the "CreateDate" property indicates that the time is one hour ahead of Greenwich Mean Time (GMT), as Paris is in Central European Standard Time (CEST). See ISO 8601 for more details.

Example (Date and time)
{
  "id": 15,
  "createdDate": "2018-10-10T12:30:10.123+01:00",
}

Security

Access tokens

All requests to our APIs need to be authenticated. This authentication is done using access_tokens (Oauth 2.0). To get an access_token you must call our token end-point and supply your ClientId and ClientSecret. Access_tokens remain valid for a limited time.

ClientIds and ClientSecrets are provided by our support organization. Please contact forstasupport@forsta.com to obtain them.

The token should ideally be cached and re-used for all requests made within the time the token is valid.
Example (Token Request)
POST  https://<host>/identity/connect/token HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded

client_id=<ClientId>&client_secret=<ClientSecret>&grant_type=api-user&scope=(1)
1 The scope indicates which API you can access. You get this when receiving your client_id and client_secret. Ex. scope=pub.surveys will indicate that you ask for a token that has access to the public survey api.
Example (Token Response)
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: ~

{
  "access_token":"4cb63760cb19552fc5cde5f37b649b7c",
  "expires_in":3600,
  "token_type":"Bearer"
}

API Versions

Our APIs are versioned in the url to the API.

Ex. http://<host>/v1/<domain> indicates that you are using version 1 of the API

Currently, our APIs are on version 1 only.

API Limits

Our public APIs have the following limits per client:

  • maximum 20 requests per second

  • maximum 1000 requests within 15 minutes

  • maximum 10000 requests within 12 hours

The number of requests are counted towards each API individually.

Exceeding the above limits will result in a 429 response from the API.

SurveyData Limits

The SurveyData endpoints '/responses/data' and 'respondents/data' habe a max PageSize of 10000 records for paged responses. PageSize larger than 10000 will result in a BadRequest (400) response. Our streaming response is not affected by this limit. See "Interact with Response Data" for more info.