TABLE OF CONTENTS
- Authentication
- Enabling/Disabling Authentication
- During Development
- HTTPS and SSL
- Caching
- Cache Refresh
- Configuration
- HTTP Methods
- HTTP Status Codes
- Errors
- Expands
- Filters
- Sorting
- Paging
- Indentation
- Examples
The Znode API is organized around REST and is designed to have predictable, resource-oriented URLs and to use HTTP response codes to indicate API errors. The API uses built-in HTTP features — such as headers, methods, and status codes — which can be understood by any off-the-shelf HTTP client. The Znode API only supports requests and responses in JSON format.
Authentication
The Znode API uses basic authentication with the Authorization header to validate requests. An example of the format for the Authorization header is shown below:
Authorization: Basic d3d3Lm15LXN0b3JlLmNvbXw1RDJCNEM1RS1EOEIzLTQ0ODgtOTA0RC02NDA5NDc2MkUxMzY=
The value 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. www.my-store.com).
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) is empty, the API request will fail with the following information:
HTTP status code: 401 Unauthorized
HTTP status description: Domain name and key are either incorrect or missing from the request Authorization header.
Enabling/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" /> (This is the Parent key, when set to true, it will start the authentication process for API.)
<add key="IsGlobalAPIAuthorization" value="true" /> (When set to true, this key will enable Global APIs Authorization. For the same, it is required to set a single API domain name and its respective API domain keys. When set to false, the individual domain name and its domain keys need to be set. )
<add key="EnableTokenBasedAuthorization" value="false" /> (When set to true, it adds the additional token-based authentication along with validating the auth header.)
Note: 'IsGlobalAPIAuthorization' Key and 'EnableTokenBasedAuthorization' will work only if 'ValidateAuthHeader' key value is set to 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 "api.localhost.com", you should add an entry in the ZnodeDomain table where the DomainName field is "api.localhost.com" 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.
HTTPS and SSL
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.
Caching
The Znode API has its own caching layer in order to provide the best possible performance when retrieving data. Caching occurs only for GET requests; it is not supported for POST, PUT, or DELETE requests.
Cache.config
All cache settings are defined in the cache.config file, a portion of which is shown below:
<ZnodeApiCache>
<cache enabled="true">
<routes>
<route template="products/{productId}" enabled="true" sliding="true" duration="60" />
<route template="products" enabled="true" sliding="true" duration="60" />
</routes>
</cache>
</ZnodeApiCache>
The root <cache> node allows you to enable or disable the entire API caching mechanism. If set to false, then no caching will occur at all for any routes.
The <routes> node contains a list of <route> nodes, each with the following properties:
template - The route template as defined in the \App_Start\WebApiConfig.cs file.
enabled - True/false value that determines if caching is enabled for the route (default = true).
sliding - True/false value that determines if a sliding cache is used for the route; if false, absolute caching is used (default = true).
duration - The number of seconds that the response data for the route should be kept in cache (default = 60 seconds).
Cache Refresh
In addition to the caching settings defined in the cache.config file, you can refresh the cache for a route by using the cache parameter and setting its value to "refresh", such as in this example:
GET http://api.mysite.com/products/302?cache=refresh
This will force the request to clear the cache for the route, retrieve fresh data, and then re-populate the cache for the route with the new data.
Configuration
The default configuration for the Znode API should work for most implementations. However, there are a couple configuration items worth noting:
<add key="UriItemSeparator" value="," />
<add key="UriKeyValueSeparator" value="~" />
Both of these settings are found in the <appSettings> section of the web.config file and are used to determine which characters to use to delimit the URI. For example, look at the following URI:
GET http://api.mysite.com/products?filter=name~cn~pea,saleprice~gt~4.99
This request says to get the list of products where the product name contains "pea" and where the sale price is greater than $4.99. The filter part of the request (explained further below) is split into two items — name~cn~pea and saleprice~gt~4.99 — based on the UriItemSeparator setting, the default of which is the comma. Each of these is then split into three values, based on the UriKeyValueSeparator, the default of which is the tilde (~) character.
But what if the product catalog is for Great Britain, where the comma is used for decimal places instead of the period? This would make the above request look like this:
GET http://api.mysite.com/products?filter=name~cn~pea,saleprice~gt~4,99
This will cause an error when splitting the URI; therefore, in cases such as this, the UriItemSeparator and UriKeyValueSeparator values should be changed. The Znode API will use those settings to split the request URI accordingly.
HTTP Methods
The Znode API uses standard HTTP methods as actions for all API requests, and most URIs accept multiple HTTP methods (one per request). The table below is a general rule of thumb for which HTTP methods are used and when.
Method | Description |
GET | Retrieves a single object or a list of objects. |
POST | Creates an object. |
PUT | Updates an object. |
DELETE | Deletes an object. |
HTTP Status Codes
The Znode API uses standard HTTP response codes to indicate the success or failure of an API request. In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that resulted from the provided information, and codes in the 5xx range indicate a server error.
Code | Description | Method Usage |
200 OK | The request was successful. | GET, PUT success |
201 Created | The item sent in the request was successfully created. | POST success |
204 No Content | The request was successful, but there was nothing to return. | DELETE success |
403 Forbidden | API key was invalid or not supplied. | Any |
404 Not Found | The requested item doesn't exist. | GET failure |
500 Internal Server Error | Something went wrong processing the request. | GET, POST, PUT, DELETE failure |
Errors
The Znode API has robust error-handling capabilities and will include additional information about the error if an HTTP 500 status code is returned. Every response from the Znode API includes the following properties:
Name | Description |
ErrorCode | A nullable integer that represents the error code for the error that occurred (default = null). Reserved for future use. |
ErrorMessage | A string that represents the description or reason for the error (default = null). |
HasError | A boolean that indicates whether or not there was an error while processing the request (default = false). |
Below is an example of what these properties look like as part of a response:
{
"ErrorCode": null,
"ErrorMessage": "SKU ID 304 does not exist.",
"HasError": true
}
Expands
The Znode API supports the concept of expands, which allows a client to retrieve related entities for a given item during the same request, and made possible with the expand parameter. For example, a client can retrieve a product (id = 329) and its images by using the following endpoint:
GET http://api.mysite.com/products/329?expand=images
A client can request multiple expands by concatenating them together, separated by a comma. For example, to retrieve the same product, but with its images, addons, and promotions, a client would use the following endpoint:
GET http://api.mysite.com/products/329?expand=images,addons,promotions
If an endpoint supports expands, there will be an Expands section as part of its help page; otherwise, no Expands section will be shown.
Filters
The Znode API also supports filters, which are essentially SQL where clauses that limit the results for a request. The filter parameter consists of tuples, with each item in the tuple separated by the ~ character. The filter tuple takes the following format:
key~operator~value
Below is the list of supported filter operators:
Operator | Description | Example |
eq | Equal to | filter=name~eq~apple |
ne | Not equal to | filter=name~ne~apple |
cn | Contains | filter=name~cn~pea |
gt | Greater than | filter=retailprice~gt~4.99 |
ge | Greater than or equal to | filter=retailprice~ge~5.00 |
lt | Less than | filter=retailprice~lt~5.00 |
le | Less than or equal to | filter=retailprice~le~4.99 |
sw | Starts with | filter=name~sw~app |
ew | Ends with | filter=name~ew~pple |
For example, to retrieve all products whose name contains "pea", a client will use the following endpoint:
GET http://api.mysite.com/products?filter=name~cn~pea
A client can also use multiple filter tuples, separated by a comma, to limit results even further. For example, to retrieve all products whose name contains "pea" and whose sale price is greater than $4.99, a client will use the following endpoint:
GET http://api.mysite.com/products?filter=name~cn~pea,saleprice~gt~4.99
The Znode API filters can also be used to query for nullable items by using a "null" value for the eq (equal to) and ne (not equal to) operators, as such:
GET http://api.mysite.com/products?filter=externalid~eq~null
GET http://api.mysite.com/products?filter=externalid~ne~nullIf an endpoint supports filters, there will be a Filters section as part of its help page; otherwise, no Filters section will be shown.
Sorting
When retrieving lists of items, the Znode API supports using the sort parameter to sort the results. For example, to retrieve all products sorted by name in ascending order, a client will use the following endpoint:
GET http://api.mysite.com/products?sort=name~asc
The sort parameter consists of key-value pairs, as separated by the ~ character. This allows a client to use multiple sorts on a set of results, with each key-value pair separated by a comma. For example, to retrieve all products sorted by name in ascending order and then by retail price in descending order, a client will use the following endpoint:
GET http://api.mysite.com/products?sort=name~asc,retailprice~desc
If an endpoint supports sorting, there will be a Sorting section as part of its help page; otherwise, no Sorting section will be shown.
Paging
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, a client will use the following endpoint:
GET http://api.mysite.com/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 ~ character and should always be used together, separated by a comma. Note that the index key-value pair is 0-based.
For endpoints 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. |
If an endpoint supports paging, there will be a Paging section as part of its help page; otherwise, no Paging section will be shown. Below is an example of what these properties look like as part of a response:
{
"PageIndex": 3,
"PageSize": 25,
"TotalPages": 5,
"TotalResults": 108,
}
Indentation
Because all responses in the Znode API are 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, a client can use the indent parameter for better readability, as such:
GET http://api.mysite.com/attributes?indent=true
Setting the indent parameter to true will produce a response with the JSON string properly indented, similar to this sample attributes response:
"Attributes": [
{
"AttributeId": 2,
"AttributeTypeId": 1,
"DisplayOrder": 1,
"ExternalId": null,
"IsActive": true,
"Name": "Red",
"OldAttributeId": null
}
]
Examples
Below are some examples that show how you can use different combinations of the expand, filter, sort, and page parameters to retrieve various sets of data.
Get a list of products and their SKUs, where the product name contains "pea", sorted by wholesale price in descending order
GET http://api.mysite.com/products?expand=skus&filter=name~cn~pea&sort=wholesaleprice~desc
Get a list of products and their categories, where the product name starts with "honey" and the product number contains 234
GET http://api.mysite.com/products?expand=categories&filter=name~sw~honey,number~cn~234
Get the 5th page of products (page size 10) sorted alphabetically by name
GET http://api.mysite.com/products?page=index~4,size~10&sort=name~asc
Get the 1st page of products (page size 20) sorted by sale price (lowest to highest), including their addons, categories, and reviews