Docs »



API requests are authenticated using credentials comprised of an access key and a secret key.

You can think of the access key as a username. A single worker may have multiple access keys with varying permissions for each application or service that uses the API, and each of them would have their own secret key.

Similarly, the secret key is like a password. However, unlike a traditional password, the secret key isn’t directly transmitted back to the server for verification. Instead, the secret key is combined with public details about the HTTP request (verb, path, date, query string, payload) to cryptographically sign it. Since the server also knows the secret key for each access key, it can create its own signature using the same combination of secret key and HTTP request details. If the signatures match then the request is authenticated.

Creating an API key-pair

First, enable the Web API plugin and create a key-pair.

Authenticating with the provided libraries

The process of signing a request is automatically handled by the official libraries for PHP, Perl, Python, and Node.js.

Authenticating from custom scripts

To sign an API request manually, create an MD51 signature of the following string:


  • verb

    The verb of the HTTP request: GET, PUT, POST, or DELETE. This prevents the signature of a previous request from being reused with a different verb.

  • http_date

    The RFC-2822 formatted Date: header being sent with the request. The current date should be used, but the server will tolerate a difference of no more than 10 minutes. This prevents the signature of a previous request from being reused at a later date (a “replay attack”2).

  • url_path

    The relative path of the request, without the scheme, host, or query string. For example, in the URL https://cerb.example/rest/tickets/123.json?expand=latest_message_content, the path is /rest/tickets/123.json

  • url_query_string

    The query string parameters sorted in alphabetical order. For example, the parameters name=Cerb, age=15, and status=active would be sorted as ?age=15&name=Cerb&status=active

  • payload

    The body of a PUT or POST request, or blank otherwise.

  • secret

    The secret key as a lowercase MD5 hash.

The generated signature should be sent with the request as a header in the following format:

Cerb-Auth: <access_key>:<signature>

If you're having trouble authenticating and you're sure that the signature is correct, verify that the current time is accurate on both the client and server.

All of these security considerations are moot if your secret key isn't stored securely. Make sure that custom scripts aren't world-readable on the server. You should always give API credentials the least amount of privileges required to perform the desired actions.


Let’s look at an example signature for testing your own authentication implementation.

For this request:

POST /rest/tickets/search.json?show_meta=0 HTTP/1.1
Date: Wed, 08 Feb 2017 19:53:35 GMT
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: cerb.example
Connection: close
Content-Length: 27


Using these credentials:

  • Access key: pjlfmn339fgh
  • Secret key: fw4y9fjjd5tqjlsk3u9zkjjr154xbftc

The authentication header is comprised of <access-key>:<signature>:

Cerb-Auth: pjlfmn339fgh:0cfe2f3b06552c060c8e77f7a0c875ee

In PHP, the signature is generated as follows:

$secret_hash = md5('fw4y9fjjd5tqjlsk3u9zkjjr154xbftc');

$string_to_sign = <<< EOF
Wed, 08 Feb 2017 19:53:35 GMT


echo md5($string_to_sign);

This outputs: