Using WSSE

You can get your integration credentials from your profile in Penneo here:

Once you have them, you're almost ready to start sending requests.
Before you do, you have to generate a new set of authentication headers for every API request that you make.

The header looks like this:

X-WSSE: UsernameToken Username="_your_key_", PasswordDigest="_digest_", Nonce="_nonce_", Created="2015-10-19T10:22:35Z"

It contains your username, a calculated Password Digest, a nonce, and the timestamp at which the digest was created.

Requirements for the nonce
You'll need to calculate the value used for PasswordDigest. In order to do that, you'll need to create a nonce. The nonce can be any random string with the following requirements:

  • It should be unique for every request
  • It needs to be a string not longer than 64 chars

Generating the headers

Here are some examples of how you can generate the authentication headers using WSSE:

function generateHeaders($key, $secret)
    $nonce   = hash('sha512', uniqid(true));
    $created = date('r');
    $digest  = base64_encode(sha1(base64_decode($nonce) . $created . $secret, true));

    return [
        'Authorization'  => 'WSSE profile="UsernameToken"',
        'X-WSSE'         => "UsernameToken Username=\"{$key}\", PasswordDigest=\"$digest\", Nonce=\"$nonce\", Created=\"$created\"",
        'Accept-charset' => 'utf-8',
        "Accept"         => 'application/json',
        'Content-Type'   =>'application/json'
def generate_headers(key, secret):
    timestamp ="%Y-%m-%dT%H:%M:%SZ")
    nonce = generate_nonce()
    digest = '{}{}{}'.format(base64.b64decode(nonce).decode('utf-8'), timestamp, secret)
    hashed_digest = hashlib.sha1(bytes(digest, 'utf-8')).digest()
    encoded_hashed_digest = base64.b64encode(hashed_digest).decode('utf-8')

    username_token = 'UsernameToken Username="{}", PasswordDigest="{}", Nonce="{}", Created="{}"'.format(key, encoded_hashed_digest, nonce, timestamp)

    headers = {
        'Authorization': 'WSSE profile="UsernameToken"',
        'X-WSSE': username_token,
        'Accept-charset': 'utf-8',
        'Accept': 'application/json',
        'Content-Type': 'application/json'

    return headers
// Have look here:
// @see:
const { UsernameToken } = require('wsse');

// Generates headers to be used in every authenticated request
function generateHeaders(key, secret) {
    const token = new UsernameToken({
        username: key,
        password: secret
    return {
        'Authorization': 'WSSE profile="UsernameToken"',
        'X-WSSE': 'UsernameToken ' + token.getWSSEHeader({nonceBase64: true}),
        'Accept-charset':  'utf-8',
        "Accept":  'application/json',
        'Content-Type': 'application/json'


    request.get('api/v1/casefiles', {
        headers: generateHeaders('myAPIKey', 'myAPISecret')

Helper utilities

You can have a look at this utility that helps generate the wsse header:
(Keep in mind that the nonce is base64 encoded in the above utility)

You can even get a WSSE Chrome plugin (here: )

Note: You should not input production passwords into untrusted websites. Use only when testing on Sandbox.