API Series: Help and Documentation

There are a lot of traits that make an API great. Easily consumable, predictable, discoverable, wide open, and a consistent URL design are the first that come to mind. But an often overlooked and undervalued area is documentation. Without proper documentation, developers are left to fend for themselves trying to figure out how to use an API, which is both time-consuming and error-prone. We’ve all been there, frustrated by an API and its lack of documentation.

Of course, there are some shining examples of API documentation done right – the Stripe API and the Github API immediately come to mind. Both are formatted and laid out well, easy to read, and contain all necessary information required to use their respective APIs.

For the Znode API, we knew from the beginning that documentation would play a major factor, and in fact, we quite often used other API docs as inspiration (in particular the Stripe API). We wanted users of the Znode API to feel at home and comfortable, and one of the best ways to do that is by providing clear, understandable documentation.

In fact, we went so far as to make the Znode API documentation simply *part* of the API itself (you can see a version of it at There is no Word document or PDF file that you have to read through to know how to use the API. The API is a living, breathing artifact that you can understand as you use the various endpoints. The homepage of the API lays out all of the parts that make up the API and what they mean, while each endpoint help page lists all of its supported features and sample data to get you up to speed quickly (which also serve as the perfect reference material).

The Znode API documentation is as vital to the API as the API itself, because in our eyes, they are one and the same.


API Series: Authentication

Security is a big deal with anything on the web, and APIs are no exception. Many times an API provider requires authentication to verify the caller has permissions to make a request and usually some type of access key is required. The Znode API follows this same convention and makes it easy to authenticate requests to its endpoints.

Like many other APIs, the Znode API uses basic authentication with the Authorization header to validate requests. An example of the format for the Authorization header is as follows:

Authorization: Basic d3d3Lm15LXN0b3JlLmNvbXw1RDJCNEM1RS1EOEIzLTQ0ODgtOTA0RC02NDA5NDc2MkUxMzY=

The value you see after the word “Basic” is a Base64 encoded string that consists of a username and password separated by a pipe character (username|password), as described below:

Username This is the domain name for the store whose data will be retrieved during the request (i.e.
Password This is the API key for the domain, as found in the ZNodeDomain table in the Multifront database (i.e. 5D2B4C5E-D8B3-4488-904D-64094762E136).

Any client of the Znode API must concatenate the domain name (username ) with the domain key (password), separated by a pipe, and then Base64 encode that string to pass along in the Authorization header.

When a request is made to an endpoint, the Znode API will look for the Authorization header and try to decode it. It will then split the decoded string into the domain name (username) and domain key (password), verify that they are a match, then process the request.

If the Authorization header isn’t in the request or if either the domain name (username) or domain key (password) are empty, the API request will fail with the following information:

HTTP status code 403 Forbidden
HTTP status description Domain name and key are either incorrect or missing from the request Authorization header.

Disabling Authentication

Authentication can be disabled by setting ValidateAuthHeader to false in the <appSettings> section of the API’s web.config file. However, in most cases, this value should be set to true in production environments.

<add key="ValidateAuthHeader" value="true" />

During Development

When developing a client that uses the Znode API, it will be useful at times to open endpoints in a browser in order to see data. To ensure this is possible, you need to add an entry in the ZNodeDomain table for the domain of the API itself. In this case, simply disabling authentication will have no effect.

For example, if you have the API deployed locally at “”, you should add an entry in the ZNodeDomain table where the DomainName field is “” with the relevant portal ID. This will be the context for retrieving data when viewing endpoints in a browser.

IMPORTANT: This should be for development purposes only.


The requirement to run under HTTPS is specific to your requirements and infrastructure; therefore, the Znode API doesn’t force you to use HTTPS to run it. However, we strongly recommend it, especially for production environments. During development, it would be beneficial to create and install a local SSL certificate in order to properly mimic all calls to the Znode API.


API Series: Cache Refresh

We’ve talked before of the power and flexibility of the Znode API caching layer, but there’s a recent addition to our API that you might find useful – the cache refresh parameter. This little baby is very useful in scenarios where you want to refresh the cache for an endpoint *before* it’s scheduled to refresh on its own.

For example, let’s say you are caching individual products for 15 minutes, which means your cache.config file would look like this:

    <cache enabled="true">
            <route template="products/{productId}" enabled="true" sliding="true" duration="900" />

If you need to dump the cache for product with ID 302 before its 15 minute cache duration is completed, then you can use the cache refresh parameter, like so:

GET /products/302?cache=refresh

This will remove the product from cache, retrieve it again from the database, then put it back into the cache for the next call. Simple but effective.


API Series: Indentation for Humans

APIs are built for machines, and when it comes to working with data inputs and outputs, machines are very good at parsing and interpreting data very quickly. With all responses in the Znode API as JSON strings, it can sometimes be hard to read responses with the human eye, especially for large responses. While this doesn’t matter to machines, it can be useful at times to open an endpoint in a browser to see the results. For this, you can use the indent parameter for better readability.

Take for example the following endpoint to get the list of payment gateways:

GET /paymentgateways

If you open this endpoint in a browser, you’ll see something like this on screen:

{"PaymentGateways":[{"Name":"Authorize.Net","PaymentGatewayId":1,"Url":""},{"Name":"Verisign PayFlow Pro","PaymentGatewayId":2,"Url":""},{"Name":"Paymentech Orbital","PaymentGatewayId":3,"Url":""},{"Name":"PayPal Direct Payment","PaymentGatewayId":4,"Url":""},{"Name":"WorldPay","PaymentGatewayId":5,"Url":""},{"Name":"CyberSource","PaymentGatewayId":6,"Url":""},{"Name":"Custom","PaymentGatewayId":7,"Url":"NA"}],"PageIndex":null,"PageSize":null,"TotalPages":null,"TotalResults":null,"ErrorCode":null,"ErrorMessage":null,"HasError":false}

Granted, it’s not a massive amount of data, but you can still make it easier for your own human eyes to comprehend that response by using the indent parameter and setting it to true, as such:

GET /paymentgateways?indent=true

Now when you open that endpoint in a browser, you get back the exact same response, but formatted for human readability:

  "PaymentGateways": [
      "Name": "Authorize.Net",
      "PaymentGatewayId": 1,
      "Url": ""
      "Name": "Verisign PayFlow Pro",
      "PaymentGatewayId": 2,
      "Url": ""
      "Name": "Paymentech Orbital",
      "PaymentGatewayId": 3,
      "Url": ""
      "Name": "PayPal Direct Payment",
      "PaymentGatewayId": 4,
      "Url": ""
      "Name": "WorldPay",
      "PaymentGatewayId": 5,
      "Url": ""
      "Name": "CyberSource",
      "PaymentGatewayId": 6,
      "Url": ""
      "Name": "Custom",
      "PaymentGatewayId": 7,
      "Url": "NA"
  "PageIndex": null,
  "PageSize": null,
  "TotalPages": null,
  "TotalResults": null,
  "ErrorCode": null,
  "ErrorMessage": null,
  "HasError": false

So while not a mission critical piece of the Znode API, the indent parameter is very useful for those times when you just need to see an endpoint response in a browser.


API Series: Sorting and Paging

Last we left the API series, we were talking about expands and filters and the flexibility they provide when querying data. So today we’re going to discuss paging and sorting, which is extremely important for limiting the amount of data you need at any given time, and how it should be sorted when it gets back to you.


When retrieving a list of items, the Znode API supports using the sort parameter to sort the results. The sort parameter is a key-value pair separated by the tilde (~) character, which is configurable. There are only two acceptable values, asc for ascending order and desc for descending order:


For example, to retrieve all products sorted by name in ascending order, you would use the following endpoint:

GET /products?sort=name~asc

And of course you can combine sorting with expands and filters. For example, to get a list of products and their SKUs, where product name contains “pea”, sorted by wholesale price in descending order, you would make the following API call:

GET /products?expand=skus&filter=name~cn~pea&sort=wholesaleprice~desc


In many cases, retrieving lists of items needs to be done a page at a time, which the Znode API handles by providing the page parameter. For example, to retrieve page 4 of a list of products with a page size of 25, you will will use the following endpoint:

GET /products?page=index~3,size~25

The page parameter consists of two key-value pairs: index and size. Both key-value pairs are separated by the tilde (~) character and should always be used together, separated by a comma.

NOTE: The index key-value is 0-based.

For endpoints in the Znode API that support paging, the following properties will be returned in the response:

Property Description
PageIndex The current page index that was requested.
PageSize The current page size that was requested.
TotalPages The total number of pages for the request.
TotalResults The total number of results for the request.

And here is an example of what these properties look like as part of the JSON response:

    "PageIndex": 3,
    "PageSize": 25,
    "TotalPages": 5,
    "TotalResults": 108,