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.

Note: Sections that are styled like this are not implemented yet.

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’re using the API, it’s always through an existing user in 4me. There’s no special API user. So when you use the API as “howard.tanner@example.com”, you can access the data that ‘Howard Tanner’ can access and perform the same actions that he is authorized to perform.

Authenticating is performed using Basic Authentication, and API Tokens are supported.

API Tokens are the preferred way to access the 4me API.

Basic Authentication:

$ curl -u "email:password" https://api.4me.com/v1/me

API Tokens:

Your API Token can be found by clicking on your avatar at the upper right corner, selecting the menu option My Profile, opening the API section and clicking on the Reveal button.

The API Token can be provided via the ?api_token= query parameter, or wrapped in the Basic Authentication.

$ curl https://api.4me.com/v1/me?api_token=api-token

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

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 acounts (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" 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" 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"
    },
    "..."
  ]
}

JSON-P Callbacks

You can add a ?callback parameter to any request to have the results wrapped in a javascript function. This is typically used when browsers want to embed 4me content in web pages by getting around cross domain issues. The response includes the same data output as the regular API, plus the relevant HTTP header information.

$ curl https://api.4me.com/v1/requests?callback=foo

foo({
  "meta": {
    "status": 200,
    "X-Pagination-Current-Page": "1",
    "X-Pagination-Per-Page": "20",
    "Link": [
      ["https://api.4me.com/v1/requests?page=1", {"rel": "first"}],
      ["https://api.4me.com/v1/requests?page=2", {"rel": "next"}]
    ]
  },
  "data": {
    // the data
  }
})

You can write a javascript handler to process the callback like this:

function foo(response) {
  var meta = response.meta
  var data = response.data
  console.log(meta)
  console.log(data)
}

All of the headers have the same String value as the HTTP headers with one notable exception: Link. Link headers are pre-parsed for you and come through as an array of [url, options] tuples.

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 openening 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.

Once a rate limit window is exceeded an error reponse 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"
}

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 couldn’t 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.