PrintOS API Authentication

Urgent notice and change announcement, in effect March 30th 2022:

PrintOS API authentication moving from SHA1 to SHA256.

PLEASE READ/CLICK HERE


Generating a Key/Secret

Before you can authenticate to the PrintOS APIs you must generate a Key/Secret from within a PrintOS account.

Within PrintOS:

  1. Click the application switcher  at the top right and select "Marketplace"
  2. Select the "Application Connectors" tab.
  3. Click the "Add Connector" tile
  4. Under the "Description" field give a descriptive name that you will remember (i.e. "My Application API Key").
  5. From the "Filter by Application" drop-down select the application you wish to generate this Key/Secret for.
  6. From the "Role" drop-down menu select the roll needed for the API you want to use
  7. Click the "Add" button to generate the Key/Secret
  8. Return to the "Application Connectors" tab to view your Key/Secret

CAUTION:  Providing this Key/Secret to a 3rd party will allow control over these APIs to your account.  Only provide this information to trusted parties.

 

A note about Key/Secret roles:

  • Order Creation - Allows for submission of orders, uploading of files, and querying of those orders/files
  • Order Creation and Enquiries - Allows for Order Creation as well as querying of various system information (Product types, SKUs, etc.)
  • Print Beat data access - Allows you to query Print Beat data including historic, near-real time, Color Beat* and OEE data (* requires subscription)
  • Jobs Enquiries - Access job-specific information for supported devices at Print Beat API - jobs context.
  • Composer SDK - Upload variable data components and render PDF outputs using PrintOS Composer.
     

Need Access to PrintOS?

Want to get started with the APIs but don't have a PrintOS account? Click the button below and fill out the form to request a development account. To expedite the request, be sure to provide as much information as possible. 

Request Access

 

HTTP Headers

In order to process any requests over the API the external application must provide the following HTTP header fields:

  • x-hp-hmac-authentication - Key:Signature format where Key is the key created through PrintOS and Signature is a generated HMAC Hex String (see below).
  • x-hp-hmac-date - Current timestamp in ISO 8601 format (YYYY-MM-DDThh:mm:ss.sssZ). Note: Timestamp must be in UTC (GMT / Zulu) time as denoted by the trailing 'Z'.
  • x-hp-hmac-algorithm Should be set to “SHA256”.  This header must be provided moving forward.

The Signature used for the x-hp-hmac-authentication header is a signed message using the SHA256 algorithm with the PrintOS generated Secret. The format for the message to sign is: method + " " + path + timestamp where:

  • method - HTTP method used to send this message (e.g. POST, PUT, DELETE).  This value must be in ALL CAPS.
  • path - Endpoint this message is being sent to (e.g. "/api/partner/folder").
  • timestamp - A timestamp generated at time of submission.  The timestamp is the same ISO 8601 (24 hour clock) format as the x-hp-hmac-date header.

Example message to sign: “POST /partner/api/folder2016-04-15T12:00:00.000Z”


Below showcases a way to generate the HMAC Headers. Visit our GitHub to checkout additional sample code.

C#
private static void CreateHmacHeaders(string method, string path, HttpClient client)
{
    string timeStamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");

    string stringToSign = method + " " + path + timeStamp;
    HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
    byte[] bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
    string signature = BitConverter.ToString(bytes).Replace("-", string.Empty).ToLower();
    string auth = key + ":" + signature;

    client.DefaultRequestHeaders.Add("x-hp-hmac-authentication", auth);
    client.DefaultRequestHeaders.Add("x-hp-hmac-date", timeStamp);
    client.DefaultRequestHeaders.Add("x-hp-hmac-algorithm", "SHA256");
}
Java
public String getHmacAuthentication(String method, String path, String timeStamp) throws InvalidKeyException, NoSuchAlgorithmException {
    SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
    Mac mac = Mac.getInstance("HmacSHA256");
    mac.init(secret_key);

    String toHash = method + " " + path + timeStamp;
    byte[] rawHmac = mac.doFinal(toHash.getBytes());
    StringBuilder hash = new StringBuilder();
    for (byte b : rawHmac) {
        hash.append(String.format("%02x", b & 0xff));
    }
        
    return key + ":" + hash.toString();
}
JavaScript
function createHeaders(method, path) {
    var timestamp = (new Date()).toISOString()
    var toSign = method.toUpperCase() + " " + path + timestamp
    var hash = crypto.createHmac("sha256", secret)
    hash.update(toSign)
    var sig = hash.digest("hex");

    var headers = {
        "X-HP-HMAC-Authentication": key + ":" + sig,
        "X-HP-HMAC-Date":  timestamp,
        "X-HP-HMAC-Algorithm": "SHA256"
    }

    return headers;
}
PHP
function createHmacAuth($method, $path, $timestamp) {
    global $key, $secret;
    $str = $method . ' ' . $path . $timestamp;
    $hash = hash_hmac('sha256', $str, $secret);
    return $key . ':' . $hash;
}
Python
def create_headers(method, path, timestamp):
    string_to_sign = method + ' ' + path + timestamp
    local_secret = secret.encode('utf-8')
    string_to_sign = string_to_sign.encode('utf-8')
    signature = hmac.new(local_secret, string_to_sign, hashlib.sha256).hexdigest()
    auth = key + ':' + signature
    return {
        'content-type': 'application/json',
        'x-hp-hmac-authentication': auth,
        'x-hp-hmac-date': timestamp,
        'x-hp-hmac-algorithm' : 'SHA256'
    }
Ruby
def create_hmac_auth(method, path, timestamp)
    str = method + ' ' + path + timestamp;
    hash = OpenSSL::HMAC.hexdigest("SHA256", $secret, str)
    return $key + ":" + hash
end