4me REST API - Introduction

This page offers an introduction to the REST (or Representational State Transfer) API of the 4me service. This API is used for retrieving, creating and updating 4me records like Requests, Changes, CIs, Services, SLAs, People, etc.

The following topics are covered in this introduction:

Information about generic REST API functionality like Pagination or Filtering, can be found in the submenu below the General option on the right.

Service URL

The 4me API has a single point of entry:

https://api.4me.com/v1

Please note the use of https:// in the URL above. All 4me API communication is encrypted over HTTPS. Any non-secure requests are automatically rejected, so we recommend establishing a test connection with the secure API entry point before sending sensitive data.

$ curl -i https://api.4me.com/v1
Status: 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 2
{}

Schema

All data is sent and received as JSON.

$ curl -i https://api.4me.com/v1/me
Status: 200 OK
Content-Type: application/json; charset=utf-8
X-RateLimit-Limit: 3600
X-RateLimit-Remaining: 3542
Content-Length: 2198
{
  "name": "My User Name",
  "site": {
    "name": "My Site Name",
    "id": 13
  },
  "...": "..."
}

See the Data Types section for detailed information on the formatting of the values.

HTTP Verbs

The API is RESTful, meaning that the HTTP verbs are used for specific actions.

GET
Used for retrieving resources.
POST
Used for creating resources, or to link resources.
PATCH
Used for updating resources with partial JSON data. PATCH is a relatively new and uncommon HTTP verb, so resource endpoints also accept PUT requests.
DELETE
Used to remove a resource from a collection.

Mime Type

The only mime type the 4me API supports is:

application/json

4me does not define any custom mime types.

You may explicitly set the Accept header when you make a request and/or end the path with .json. If both are omitted 4me defaults to returning a JSON response.

The following are all equivalent:

$ curl -H "Accept: application/json" https://api.4me.com/v1/me

$ curl https://api.4me.com/v1/me.json

$ curl https://api.4me.com/v1/me

Authentication

When you are using the 4me REST API, it is always through an existing user in 4me. There is no special API user. When authenticating as an existing user in 4me, you can access the data that the user can access, and perform the actions that the user is authorized to perform.

Each request to the 4me REST API must supply two HTTP headers:

An OAuth token can be obtained by generating a Personal Access Token from My Profile in 4me. The 4me account ID value passed in the X-4me-Account header determines the current account that the API request will use.

The 4me REST API can also be accessed by providing an API Token using Basic Authentication. In that case the header X-4me-Account is not required, and will default to the account of the user. The use of API Tokens is discouraged though, and the prefered authentication mechanism is the use of the more secure OAuth Tokens.

Personal Access Tokens

A personal access token is an OAuth Token, and must be provided as part of the Bearer Authentication:

$ curl -H "Authorization: Bearer <oauth-token>" \
       -H "X-4me-Account: widget" \
       https://api.4me.com/v1/me

Note that for this example to work your personal access token must have added a scope to allow action me - All.

Your personal access tokens can be found by clicking on your avatar in the upper right corner, and selecting the menu option My Profile

API Token 1

Open the Personal Access Tokens section, click on the Generate token button to generate a new token.

Personal Access Token 1

After saving the form, the new token is displayed:

Personal Access Token 2

API Tokens

Consider using personal access tokens instead of an API token, and disable your API token. Personal access tokens are more secure and allow you to use a separate token for different purposes.

Your API Token can be found by clicking on your avatar in the upper right corner, and selecting the menu option My Profile

API Token 1

Open the API section, click on the Reset API token button and confirm the reset.

API Token 2

The API token should be provided via Basic Authentication.

$ curl -u "api-token:x" https://api.4me.com/v1/me

When using Basic Authentication the API token should be placed in the user part (before the colon). The password part will be ignored and can be set to anything.

Older clients are allowed to pass the API Token via the ?api_token= query parameter. This is strongly discouraged! Please use Basic Authentication instead, or better yet, convert to using Personal Access Tokens.

To reset the API Token using the REST API:

$ curl -u "api-token:x" -X POST https://api.4me.com/v1/me/reset_api_token

Multiple Accounts

Often the account of the authenticated user has several trust relations with other accounts. As a result, resources from other accounts (mostly SLA’s, Requests, Teams and People) are accessible through the API.

Each reference to a resource that belongs to a different account will receive an account hash with the name and id of that account, see references for more details.

Switching Accounts

The authenticated user may have access rights to one or more trusted accounts. To retrieve information from those accounts through the API, add the X-4me-Account header to the API request.

In this example the authenticated user has access to the Widget North America account:

 $ curl -H "X-4me-Account: wna-it" https://api.4me.com/v1/sites?fields=name
Status: 200 OK
[
  {
    "name": "Widget Data Center",
    "id": 14
  },
  {
    "name": "Widget International Headquarters",
    "id": 15
  },
  {
    "name": "Widget Manufacturing Center",
    "id": 16
  },
  {
    "name": "Widget Research & Development Center",
    "id": 17
  }
]

And the Widget Europe account:

 $ curl -H "X-4me-Account: weu-it" https://api.4me.com/v1/sites?fields=name
Status: 200 OK
[
  {
    "name": "Widget European Headquarters",
    "id": 18
  }
]

Internationalization

Most API calls are language independent. In some cases the response contains translated values, e.g.:

By default the language of the authenticated user is taken, see the Personal Preferences screen found under the Settings menu in 4me. To override this setting, add the X-4me-Language header to the API request.

 $ curl -H "X-4me-Language: nl" https://api.4me.com/v1/enums
Status: 200 OK
{
  "request.status": [
    {
      "id": "declined",
      "txt": "Geweigerd"
    },
    {
      "id": "assigned",
      "txt": "Toegewezen"
    },
    {
      "id": "accepted",
      "txt": "Geaccepteerd"
    },
    {
      "id": "etc",
      "txt": "etc"
    }
  ],
  "etc": "..."
}

All supported language codes can be found via the Enumerations API, see the language key:

{
  "language": [
    {
      "id": "en-US",
      "txt": "English (United States)"
    },
    {
      "id": "nl",
      "txt": "Nederlands"
    },
    {
      "id": "fr",
      "txt": "Francais"
    },
    {
      "id": "da",
      "txt": "Dansk"
    },
    {
      "id": "et",
      "txt": "Eesti"
    },
    "..."
  ]
}

Rate Limiting

Authenticated API requests are associated with the authenticated user. Unauthenticated API requests are associated with the originating IP address, and not the user making requests.

The returned HTTP headers of an API request show the current rate limit status:

$ curl -i https://api.4me.com/v1/me
Status: 200 OK
X-RateLimit-Limit: 3600
X-RateLimit-Remaining: 3599
X-RateLimit-Reset: 1533873527
X-RateLimit-Limit
The maximum number of requests permitted to make in the current rate limit window.
X-RateLimit-Remaining
The number of requests remaining in the current rate limit window.
X-RateLimit-Reset
The time at which the current rate limit window resets in UTC epoch seconds.

If the reset time is needed in a different format then any modern programming language can be used to achieve this. For example, if opening up the console of a web browser, the reset time can be returned as a JavaScript Date object as follows:

new Date(1533873527 * 1000)
=> Fri Aug 10 2018 03:58:47 GMT+0000 (UTC)

You can check your rate limit status without incurring an API hit, but accessing this endpoint is limited to once per second.

Responding to rate limiting conditions

Once a rate limit window is exceeded an error response is returned and the HTTP header Retry-After indicates how long to wait (in seconds) before making a new request:

Status: 429 Too Many Requests
Content-Type: application/json; charset=utf-8
Retry-After: 30
{
  "message": "Too Many Requests",
  "documentation_url": "https://developer.4me.com/v1/#rate-limiting"
}

This response instructs your app to wait 30 seconds before attempting to send a new request.

By programmatically evaluating the Retry-After header you can wait for the indicated number of seconds before retrying the same request.

HTTP Status Codes

The 4me API attempts to return appropriate HTTP status codes for every request.

200 OK - Success!

 $ curl https://api.4me.com/v1/me
Status: 200 OK
Content-Type: application/json; charset=utf-8

204 No Content - Success, no data to return

 $ curl https://api.4me.com/v1/me
Status: 200 OK
Content-Type: application/json; charset=utf-8

304 Not Modified - There was no new data to return

 $ curl -H 'Etag: 1234567890' https://api.4me.com/v1/me
Status: 304 Not Modified
Content-Type: application/json; charset=utf-8

400 Bad Request - Incorrect parameter values or syntax error in JSON

 $ curl -i https://api.4me.com/v1/cis?per_page=-10
Status: 400 Bad Request
Content-Type: application/json; charset=utf-8
{
  "message": "Parameter 'per_page' cannot be less than 1"
}

401 Unauthorized - Invalid or missing authentication credentials

 $ curl -i -u "user:invalid" https://api.4me.com/v1/me
Status: 401 Unauthorized
Content-Type: application/json; charset=utf-8
{
  "message": "Access credentials required"
}

403 Forbidden - Access to resource is not allowed with current credentials

 $ curl -i https://api.4me.com/v1/people/1
Status: 403 Forbidden
Content-Type: application/json; charset=utf-8
{
  "message": "Forbidden"
}

404 Not Found - The URI is invalid or the resource requested does not exist

 $ curl -i https://api.4me.com/v1/me_too
Status: 404 Not Found
Content-Type: application/json; charset=utf-8
{
  "message": "Not Found"
}

406 Not Acceptable - URI is known but does not accept JSON API requests

 $ curl -i https://api.4me.com/v1/account/billing
Status: 406 Not Acceptable
Content-Type: application/json; charset=utf-8
{
  "message": "Not Acceptable"
}

422 Unprocessable Entity - Semantic error in provided data

 $ curl -i -X POST -F impact=medium https://api.4me.com/v1/requests
Status: 422 Unprocessable Entity
Content-Type: application/json; charset=utf-8
{
  "message": "Validation Failed",
  "errors": [
    [
      "subject",
      "Subject can't be blank"
    ],
    [
      "category",
      "Category can't be blank"
    ]
  ]
}

The validation errors are tuples with the field name and a localized error message. Note that a single field may yield multiple validation errors.

429 Too Many Requests - Rate Limit Exceeded

Status: 429 Too Many Requests
Content-Type: application/json; charset=utf-8
X-RateLimit-Limit: 3600
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1533873527
Retry-After: 30
{
  "message": "Too Many Requests",
  "documentation_url": "https://developer.4me.com/v1/#rate-limiting"
}

500 Internal Server Error - Something is broken. The 4me team should investigate.

Status: 500 Internal Server Error
Content-Type: application/json; charset=utf-8
{
  "message": "Internal Server Error"
}

502 Bad Gateway - 4me is down or being upgraded

Status: 502 Bad Gateway
Content-Type: application/json; charset=utf-8
{
  "message": "Bad Gateway"
}

503 Service Unavailable - The 4me servers are up, but overloaded with requests. Try again later.

Status: 503 Service Unavailable
Content-Type: application/json; charset=utf-8
{
  "message": "Service Unavailable"
}

504 Gateway timeout - The 4me servers are up, but the request could not be serviced due to some failure at 4me. Try again later.

Status: 504 Gateway timeout
Content-Type: application/json; charset=utf-8
{
  "message": "Gateway timeout"
}

If you see an error response which is not listed in the above table, then fall back to the HTTP status code in order to determine the best way to address the error.