Appendix A - File API Client Signing

Summary of Signing Steps

You begin by determining the URI of the request itself. For example, let’s say you wanted to retrieve a list of order files which have not yet been processed. The REST endpoint for that call is the following URI, issued as a GET request.

https://file-api.fillz.com/v1/orders/created/?acknowledged=false

What follows is the set of steps required to create a valid, signed request to retrieve the data at this endpoint.

Task 1: Derive a checksum for the message content

In order to allow verification of the content of your request, you need to provide a SHA-256 checksum of your message content. In the pseudo-code below, the message_content variable contains the contents of the message you plan to send (this is the message body, without any headers). If your message content is empty (as is often the case for GET requests), substitute an empty string '' for the content checksum:

Pseudocode for generating a message content checksum:

content_checksum = ''
if (length(message_content) > 0):
    content_checksum = HexEncode(SHA256(message_content))

Sample Content Checksum for the string “sample content”

571ca3b4ef92a81f8c062f2c2437b9116435d1575589a7b64a5c607d058fde0d

Task 2: Collect Signature Elements

The unsigned request consists of a number of elements that you concatenate together into a single string ready for signing.

The first element is the request type you wish to use (GET, PUT, POST, DELETE) in all upper-case.

GET

The second element is the URI of the request itself, in canonical form. The canonical URI is the URI-encoded version of everything in the URI from the HTTP host, including any question mark character (”?”) and all query string parameters (if any). Normalize URI paths according to RFC 3986 by removing redundant and relative path components and convert everything to lower-case (except where upper-case is required in any parameters). In our case, we have:

https://file-api.fillz.com/v1/orders/created/?acknowledged=false

You are required to URI-encode this string according to the following rules:

  • Do not URI-encode any of the following characters: A-Z, a-z, 0-9, hyphen ( - ), underscore ( _ ), period ( . ), tilde ( ~ ), semicolon ( : ), or slash ( / ).
  • Percent-encode all other characters with %XY, where X and Y are hexadecimal characters (0-9 and uppercase A-F). For example, the space character must be encoded as %20 (not using ‘+’, as some encoding schemes do) and extended UTF-8 characters must be in the form %XY%ZA%BC.
  • Query parameters in the URL should be separated by the character ‘&’ (ASCII code 38) prior to encoding (not &). After encoding, ‘&’ would become ‘%26’.

The third element exists to reduce the possibility of replay attacks (someone submitting your request again at a future time). To create this element, you construct a string containing the timestamp for this request. This timestamp should be expressed in ISO8601 Basic format (YYYYMMDDThhmmssZ) using UTC. Your request is valid for five minutes from this timestamp.

X-FillZ-Date: 20140924T113735Z

The fourth element is the content_checksum calculated in Task 1.

Task 3: Create the final string

To generate the final string used to create a request signature, you must concatenate all of these elements together, placing a single newline character between each. Using the examples above, pseudo-code to create the final string would be:

Pseudocode to create the final string:

action = 'GET'
uri = 'https://file-api.fillz.com/v1/orders/created/%3Facknowledged%3Dfalse'
fillz_date = '20140924T113735Z'
content_checksum = ''
final_string = action + '\n' + uri + '\n' + fillz_date + '\n' + content_checksum

Please note that this example uses a GET with no content, so the content_checksum is blank.

Task 4: Generate the request signature

Before you can sign the final string, you will need a set of valid FillZ API credentials. These credentials consist of an access-key and a secret-key which you download from the FillZ UI by clicking on API/FTP under the Settings menu. In this example, assume the following credentials were obtained:

secret_key = 'wJalrXUtnFEMI5K7MDENGsbPxRfiCYEXAMPLEKEY'
access_key = EXAMPLEACCESSKEY

Once you have the final string prepared, you generate the request signature by using the secret-key with a SHA256 HMAC algorithm. Using the final_string from the code above, Pseudo-code is shown below:

Pseudocode for obtaining the request signature:

x_fillz_signature = HMAC(secret_key, final_string, hashlib.sha256).hexdigest()

Signature for the example in Task 3:

e45609da24ae22884f0eb59cca9105b32732f5f7420c6fd297d561d573e3414e

Task 5: Submit the Request

With the signature in hand, you are ready to submit your request to the API. To do so, call the API with the appropriate request type (GET, PUT, POST) as used in your signing, and request the URI you signed, including all parameters. In your request, provide three extra headers. The first is the X-FillZ-Date that you used during the signature. The second is your FillZ API access-key X-FillZ-Access-Key. The third is the X-FillZ-Signature which you calculated above.

The full HTTP request for the example shown above will look something like the following:

GET https://file-api.fillz.com/v1/orders/created/?acknowledged=false HTTP/1.1
X-FillZ-Date: 20140924T113735Z
X-FillZ-Access-Key: EXAMPLEACCESSKEY
X-FillZ-Signature: e45609da24ae22884f0eb59cca9105b32732f5f7420c6fd297d561d573e3414e

The body content would be blank in this case.

Sample Code

See Appendix C for samples of client signing code in Python, Java and C#.