Public API

This page represents a public API that allows partners to access our Platform services. The APIs are broken up into a series of logical sections related to the service being used and a summary of these can be found on the Service Overview page. 

Overview

API access methods

All API access is over HTTPS, and accessed from the api.acommerce.asia domain. All data is sent and received as JSON.

This example is a placeholder that does not represent a real service

$ curl -i https://api.acommerce.asia/showmewhatiordered/acme/items

HTTP/1.1 200 OK
Server: nginx
Date: Fri, 12 Oct 2012 23:33:14 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Status: 200 OK
ETag: "a00049ba79152d03380c34652f2cb612"
Content-Length: 5
Cache-Control: max-age=0, private, must-revalidate
X-Content-Type-Options: nosniff

[]

Blank fields are included as null instead of being omitted.

All timestamps are returned in ISO 8601 format:  YYYY-MM-DDTHH:MM:SSZ

HTTP Verbs

Where possible, API v2 strives to use appropriate HTTP verbs for each action.

VerbDescription
HEADCan be issued against any resource to get just the HTTP header info.
GETUsed for retrieving resources.
POST

Used for creating resources. In some scenarios where a retrieval of resources requires a JSON body as input, then a POST verb will be used.

PATCHUsed for updating resources with partial JSON data. For instance, an Issue resource has title and body attributes. A PATCH request may accept one or more of the attributes to update the resource. PATCH is a relatively new and uncommon HTTP verb, so resource endpoints also accept POST requests.
PUTUsed for replacing resources or collections. For PUT requests with no body attribute, be sure to set the Content-Length header to zero.
DELETEUsed for deleting resources.

HTTP Return Codes

All aCommerce endpoints return appropriate HTTP response codes that a client should interpret. 

Status Code
Description
200-299These generally represent success codes and should be interpreted as such. HTTP "200 OK", "201 Created" and "202 Accepted" specifically should be considered generally equivalent.
300-399See the section below on HTTP Redirects. Clients should always follow redirects
400-499HTTP Return codes in the 400 range are used to indicate that the client should take action and should NOT repeat the request without making adjustments. The only exception to this guidance is HTTP 429 which is described in the section Rate Limits section below. Almost all responses using this range of codes will also return an Errors structure to help the developer to diagnose problems.
500-599These generally represent a problem on aCommerce end of the communication. In general, it is acceptable to retry requests with the exception of HTTP 501 and HTTP 505.

HTTP Redirects

API v2 uses HTTP redirection where appropriate. Clients should assume that any request may result in a redirection. Receiving an HTTP redirection is not an error and clients should follow that redirect. Redirect responses will have a Location header field which contains the URI of the resource to which the client should repeat the requests.

Status CodeDescription
301Permanent redirection. The URI you used to make the request has been superseded by the one specified in the Location header field. This and all future requests to this resource should be directed to the new URI.
302,307Temporary redirection. The request should be repeated verbatim to the URI specified in the Location header field but clients should continue to use the original URI for future requests.

Other redirection status codes may be used in accordance with the HTTP 1.1 spec.


Authentication

All API calls with the exception of a post to the "token" service must contain an Authentication header bearing a token indicating the Application. See the Authentication page for more details about how to acquire this authentication token. 

Tokens must be provided in an HTTP header with the name: X-Subject-Token


Parameters

Many API methods take optional parameters. For GET requests, any parameters not specified as a segment in the path can be passed as an HTTP query string parameter:

Example

$ curl -i "https://fulfillment.api.acommerce.asia/channel/201456/order/b611gra?orderStatus=Error"

In this example, the ‘201456’ and 'b611gra' values are provided for the :channelID and :orderID parameter in the path while :orderStatus is passed in the query string as a constraint limiting the results to only orders in the Error state.

For POST, PATCH, PUT, and DELETE requests, parameters not included in the URL should be encoded as JSON with a Content-Type of ‘application/json’:

Example

$ curl -i -d '{"Auth:{"apiCredentials":{"username":"acme",apiKey:"#%FQTEAGAT#FQ"}}' https://api.acommerce.asia/identity/token

Client Errors

In general, all errors will be returned as HTTP Status codes. However, to aid in diagnoses, most errors will be accompanied with a JSON body that conforms to a standardized format.  In general, all APIs will utilize the following schema for returning data about an error where all fields are optional:

error : {
  code: number,
  message: "English text designed for a developer and not to be displayed to an end-user (e.g. shopper)",
  errors: [
     reason: "tokenized string specific to service providing error... not an HTTP code",
     message: "English text designed for a developer and not to be displayed to an end-user (e.g. shopper)",
     extendedHelp: "A URL that points to additional information that may help to resolve the error"
  ]
}


There are three possible types of client errors on API calls that receive request bodies:

 1. Sending invalid JSON will result in a 400 Bad Request response.
    HTTP/1.1 400 Bad Request
    Content-Length: 48

    {error: { "message":"Problems parsing JSON" } }

 2. Sending the wrong type of JSON values will result in a 400 Bad Request response.
    HTTP/1.1 400 Bad Request
    Content-Length: 54

    {error: { "message":"Body should be a JSON object"} }
 3. Sending invalid fields will result in a 422 Unprocessable Entity response.
    HTTP/1.1 422 Unprocessable Entity
    Content-Length: 149

    { 
      error: {
        "message": "Validation Failed",
        "errors": [
          {
            "reason": "missing_field"
			"message: "field orderID is required to be present"
          }
        ] 
      }
   }


All error objects have message properties so that your client can tell what the problem is. There’s also reason codes to let you know what is wrong with the field. These are the possible validation reason codes:

Error NameDescription
missingThis means a resource does not exist.
missing_fieldThis means a required field on a resource has not been set.
invalidThis means the formatting of a field is invalid. The documentation for that resource should be able to give you more specific information.
already_existsThis means another resource has the same value as this field. This can happen in resources that must have some unique key (such as Label names).

Resources may also send custom validation errors (where reason is custom). Custom errors will always have a message field describing the error, as well as a documentation_url field pointing to some content that might help you resolve the error.

In rare situations, a request may 'partially succeed' and the mechanism for communicating this will be found within the detailed description of the API call. Typically, it will involve including one or more "error" objects described above inside the JSON response body. 


Pagination

In any ERP, it is common for a request that returns multiple items to return a very large number of items. A requester should assume that any API that returns a list of objects will have a service-specified limit on the maximum numbers of items returned in a single HTTPS call. As such, all such interfaces that return large lists will support the concept of Pagination and should document the limits of a single query as part of that request description. You can specify further pages simply by following the 'next' link which often (but not always) contains a 'page=' query string pair .

Note that the definition of "what is a page" is specific to each service and that omitting the ?page parameter will return the first page. In this construct, pages can be thought of as a forward cursor where callers are navigating forward in the result-set.

Link Header

The pagination info is included in the Link header. If the link header does not contain a 'next' link, then the calling system should assume this is the last page. It is important to follow these Link header values instead of constructing your own URLs. In some instances, pagination is based on SHA1 and not on page number and in many cases, pagination is based on record counts. A service is not required to use the term 'page' in the query string to indicate the next segment of data in the result set. Services reserve the right to change pagination schemes in the future, so it is safest to just follow the 'next' links. 

Example

Link: <https://api.acommerce.asia/partner/1531526/order-status?page=3>; rel="next",
  <https://api.acommerce.asia/partner/1531526/order-status?page=50>; rel="last"

Linebreak is included for readability.

The possible rel values are:

NameDescription
nextShows the URL of the immediate next page of results.
lastShows the URL of the last page of results.
firstShows the URL of the first page of results.
prevShows the URL of the immediate previous page of results.

Not all aCommerce APIs will return first, last, and prev links. However, all APIs that implement pagination will provide a next link if there is more information to be retrieved in the resource result-set.

Rate Limits

For requests using tokens, you can make up to 100 requests per minute. Additionally, many services can have custom rate limits (typically limited to the number of orders that can be replaced over a period of time) that are designed to protect customers from run-away applications.

When you exceed these limits, you will have an HTTP 429 error returned that will also contain information in the form of a "Retry-After" header informing you when you can resume sending. An example of such a message looks like this:

Example

HTTP/1.1 429 429
Server: nginx/1.6.2
Date: Tue, 30 Jun 2015 04:52:32 GMT
Content-Length: 0
Connection: keep-alive
Retry-After: Tue, 30 Jun 2015 04:53:22 GMT
Via: 1.0 Repose (Repose/7.1.2.0)
x-trans-id: a23bf2bf-e6b8-4873-a386-aa18eda7f239

Staying within the rate limit

Most APIs are designed in such a way that you will never approach your rate limit. They allow you to reduce the number of queries to simply "things that have changed since the last time I asked".  If you’re using these APIs correctly still exceeding your rate limit, please contact us to request a higher rate limit for your application.

User Agent

You are encouraged to include a User-Agent header to aid in troubleshooting. Requests without a User-Agent header will not be rejected, but we may change this policy in a future version of this API. so, it is best to get in the habit now. 

We request that you use your aCommerce user name and the name of your application as the User-Agent header value. This will help us to contact you if there are problems.

Here’s an example:

User-Agent: Awesome-Products-App


Time Zones

Many of the APIs exposed by aCommerce accept times as a constraint for the GET request. This is typically used to help the partner manage bandwidth by getting 'delta' results. In all cases, those constraints are expecting the time to be expressed with an explicit Time Zone using an ISO 8601 format. 

Web Hooks

Many of the operations that are started against the aCommerce platform result in long running workflows to be executed. In a normal API the application would need to occasionally ask the aCommerce platform for an update on that operation to understand its progress. This occasional ask is referred to as polling and can be quite inefficient as most of the time, the answer to such a question is: "no change". The application developer is required to decide how often to poll and this is often a difficult decision to make. The Web Hook Service APIs allow a customer to register a webhook to receive notifications of change in that long running workflow. In most cases, these notifications will happen within a second of the event happening within the aCommerce infrastructure assuming the application hook is keeping up.

These Web Hook end-points are organized in the form of 'event streams'. Each workflow that supports a web hook can have a different event stream and this allows the partner to register a different HTTP end-point for different types of workflows.  The aCommerce web hook service will also support retries for failed deliveries of an event and each web hook will have a queue associated with it so that the delivery of these events is pretty reliable. A partner is able to take down the web hook end-point for a period of time without losing events.

Understanding Retries

If at any point in time, an event has been queued for an event stream subscriber, the Webhook application server will try to deliver the event by calling the end-point. The Webhook application server will process the HTTP status code returned and, depending upon the value, may consider the event delivery successful, consider the event delivery a permanent failure and move on to the next event, or it may go into a retry loop. This retry loop will delay for 60 seconds and then try to issue the HTTP(s) request to the same endpoint with the same event. Retry loops will proceed for 2880 iterations (2 days) before being considered permanently failed. Upon permanent failure, the event is discarded and the entire process begins again with the next event queued.

Normally, the webhook service will consider HTTP status code "200 OK", "201 Created" or "202 Accepted" to be a successful event delivery. HTTP status codes in the 3xx range (re-directs) will cause the service to follow the link and try to redeliver the event immediately at that new link. All HTTP status codes in the 4xx range are considered immediate permanent failures except 408 "REQUEST TIMEOUT" and 429 "TOO MANY REQUESTS". HTTP status codes of 408, 429 and those in the 5xx range will cause the service to delay for 60 seconds and then attempt to re-deliver the event. 

Webhook Service Identity Validation

By nature of the webhook service, upon receiving an update to a particular event type, the webhook service will act as a client attempting to send the update to all webhooks subscribing to the event type. These updates are sent as HTTPS POST messages and, therefore, the webhook service will act as an HTTPS client attempting to send HTTPS POSTs to the HTTPS server, which in this case, is the URL configured for each webhook. As for any HTTPS server, it is essential that the server is able to identify the identity of the client to ensure that the client is valid and is authorized to make HTTPS requests to the server. The authentication method provided by the webhook service supports signature validation which allows the webhook clients to provide a secret string to the webhook service. The webhook service will then use that string to generate an HMAC hex digest of the body of the update to be sent to the webhook client and include it in the header of the update under the parameter X-AComm-Signature. As for the webhook receiver, to validate the signature of the update, the receiver has to simply generate the HMAC hex digest of the body of the update received using the secret string provided to the webhook service and comparing it with the signature in the header of the update. If the two string matches, the update is likely to be published by the webhook service. An example Python code snippet to generate the HMAC hex digest of the body of the update is provided below.

The webhook service uses the SHA1 cryptographic hash function. 

import hmac
import hashlib
   
# Function to generate a hex digest from the HTTP request body 
# where <request> is the HTTP request and <secret> is the secret string
def get_hexdigest(request, secret):
    return hmac.new(str(secret), str(request.data), hashlib.sha1).hexdigest()