Welcome

To the Spaza.co Developer Portal


# Introduction

This guide will help you in your integration with the Spaza.co backend system.
It's designed to provide a very simple and easy to understand RESTful API through which you may query any store information, product information, place orders, and utilise this for any frontend development you'd like!

This documentation is updated almost daily, so please check back often for new endpoints and available information!


# Gaining API Access

This is the easy part - all you need to do is sign in to your Spaza.co account, select the store you'd like to integrate with, navigate to "Developer Access", and you'll be able to generate your own API Key and Client Identifier. You'll then use these two values when creating your own POST and GET requests:

alt text


# Basic Request Structure

Now that you have your API Key and Client Identifier, it's time to use them.

All API requests will expect - and respond with - JSON data objects. These will be defined for you in this documentation as we go.
Spaza.co also utilises the Cerberus API scaffold to build and host its own API infrastructure, and the following snippet illustrates the basic structure that your POST and GET requests need to follow in order to successfully integrate with the Spaza.co API:

API base URI:  https://api.spaza.co/process

Request headers:
    "cerberus-apikey"    : << your Spaza.co API Key goes here >>
    "cerberus-client"    : << your Spaza.co Client Identifier goes here >>
    "cerberus-timestamp" : << a generated timestamp (in seconds) you need to supply >>


As an example of how these are implemented, regard the JavaScript code below (using jQuery to perform an AJAX request), which will fetch our store details using the example API Key and Client Identifier shown above:

// our timestamp, in seconds since Epoch, which we'll need for our "cerberus-timestamp" header parameter...
const timestamp = Math.floor(new Date().getTime() / 1000)

// our credentials we retrieved from the Spaza.co "Developer Access" section in the backend...
const api_key = "A5DB56E4-EBBB-F04D-0350-E76C4ADCA375"
const client_identifier = "SPAZA-API-ACCESS"

// our API endpoint, using the base URI detailed above...
// not to worry, we'll go into details on each available endpoint further down in this documentation...
const endpoint = "/store-details"
const base_uri = "https://api.spaza.co/process"

// time to perform our GET request...
jQuery.ajax(
    base_uri + endpoint,
    {
        dataType : "json",
        data     : { },
        method   : "GET",
        headers  : {
            "cerberus-apikey"    : api_key,
            "cerberus-client"    : client_identifier,
            "cerberus-timestamp" : timestamp
        },
        complete : function ( retrieved_data ) {
            // do something with the retrieved data...
        }
    }
)

A few notes on the above example:

  • you will always need 3 header parameters, namely cerberus-apikey, cerberus-client, and cerberus-timestamp
  • cerberus-apikey will be populated from the API Key you generated in the Spaza.co backend for a particular store
  • cerberus-client similarly will be populated using the Client Identifier you generated in the Spaza.co backend for a particular store
  • cerberus-timestamp will need to be generated for every call - it's a simple timestamp, in seconds since Epoch
  • the endpoint /store-details is one of the endpoints you can use within this API, but we'll be detailing all available endpoints for you below

# Available endpoints

Here is a list of the available endpoints you can use in the Spaza.co RESTful API:

  1. store-details - retrieves information about your store
  2. product-categories - retrieves all available product categories
  3. products - retrieves all available products, includes categorical filtering
  4. shipping-options - retrieves a list of possible shipping carriers, could be empty
  5. payment-options - retrieves a list of possible payment options, could be empty
  6. countries-and-regions - retrieve a list of available countries, and their associated provinces / regions
  7. shipping-quotes - request a quote for shipping rates, given a set of products, their variations, and a shipping location

# 1. store-details endpoint

Request type: GET
Request endpoint: /store-details
Request parameters:

{ }

Response object - 200 Success - string values could be blank strings if not supplied yet:

{
    storeContactNumber: "0005550000",                       // String: store phone number
    storeCurrencyCode: "ZAR",                               // String: store currency code
    storeCurrencyName: "South African Rand",                // String: store currency name
    storeCurrencySymbol: "R",                               // String: store currency symbol
    storeDescription: "Description here",                   // String: store description
    storeDescriptionHtml: "Description (HTML version)",     // String: store description (HTML)
    storeEmail: "store-email@address.co.za",                // String: email address
    storeFacebookPageLink: "https://facebook.com/mystore",  // String: URI to your Facebook page
    storeId: 1234,                                          // Number: unique store ID
    storeIsActive: true,                                    // Boolean: store active flag
    storeIsFree: false,                                     // Boolean: store "is free version" flag
    storeIsSubscriber: true,                                // Boolean: store "is subscriber" flag
    storeLogo: "https://mystore.spaza.co/logo.jpg",         // String: store logo URI
    storeName: "My store name",                             // String: store name
    storeSubdomain: "mystore",                              // String: store subdomain
    storeSubscriptionTimestamp: "1590530399",               // String: store subscription end timestamp 
    storeTwitterHandle: "twitterusername",                  // String: store Twitter handle
    storeType: "multi",                                     // String: store type (currently "multi" or "tickets")
    storeUriAlias: "https://www.mystore.co.za"              // String: store alias URI
}

Response object - 400 Bad Request, or 404 Not Found:

Flat descriptive message sent back without structure.

# 2. product-categories endpoint

Request type: GET
Request endpoint: /product-categories
Request parameters:

{ }

Response object - 200 Success

[
    {
        categoryId: 123,            // Number: product category ID
        categoryLabel: "Clothing",  // String: category label / name
        childCategories: [
            {
                categoryId: 456,           // Number: child category ID
                categoryLabel: "T-Shirts"  // String: category label / name
            },
            {
                // additional child categories to follow...
                // following the same structure...
            }
        ]
    },
    {
        // additional categories to follow...
        // following the same structure...
    }
]

Response object - 404 Not Found:

Flat descriptive message sent back without structure.

# 3. products endpoint

Request type: GET
Request endpoint: /products
Request parameters:

{
    categories : [ 2, 5, 0 ]  // Array: optional, a list of category IDs to filter by
}

Response object - 200 Success

[
    {
        productId: 123,                                   // Number: product ID
        isFeaturedProduct: true,                          // Boolean: is product a featured product
        productName: "Green T-shirt",                     // String: product name
        productCaption: "Product caption",                // String: product caption
        productDescription: "Product description",        // String: product description
        productDescriptionHtml: "Description with HTML",  // String: product description including HTML formatting
        productCategories: [
            {
                categoryId: 456,           // Number: category ID
                categoryLabel: "T-Shirts"  // String: category label / name
            },
            {
                // additional categories to follow...
                // following the same structure...
            }
        ],
        productAvailableStock: -1,      // Number: current product stock, -1 for unlimited, 0 if variations exist
        productPrice: 0.00,             // Number: product price, will be 0.00 if variations exist
        hasVariations: true,            // Boolean: flag indicating if product has variations
        productVariationLabel: "Size",  // String: main product variation label (if any)
        productVariationOptions: [
            {
                variationId: 7,                 // Number: the ID of the variation
                variationLabel: 'Extra Large',  // String: the variation's label
                variationPrice: 1456.99,        // Number: variation price
                variationAvailableStock: -1     // Number: current variation stock, -1 for unlimited
            },
            {
                // additional product variations to follow...
                // following the same structure...
            }
        ],
        productImages: [
            {
                original: "https://mystore.spaza.co/image.jpg",                       // String: URI to original image
                medium: "https://mystore.spaza.co/image.jpg?medium=parameters",       // String: URI to medium image
                small: "https://mystore.spaza.co/image.jpg?small=parameters",         // String: URI to small image
                thumbnail: "https://mystore.spaza.co/image.jpg?thumbnail=parameters"  // String: URI to image thumbnail
            },
            {
                // additional images to follow...
                // following the same structure...
            }
        ]
    }
]

Response object - 400 Bad Request, or 404 Not Found:

Flat descriptive message sent back without structure.

# 4. shipping-options endpoint

Request type: GET
Request endpoint: /shipping-options
Request parameters:

{ }

Response object - 200 Success - could be an empty list if no options have been added yet:

[
    {
        shippingCarrierId: 123,        // Number: the shipping option's ID
        shippingCarrierLabel: "FedEx"  // String: the sjipping option's label
    },
    {
        // additional shipping carriers to follow...
        // following the same structure...
    }
]

Response object - 404 Not Found, or 500 Server Error:

Flat descriptive message sent back without structure.

# 5. payment-options endpoint

Request type: GET
Request endpoint: /payment-options
Request parameters:

{ }

Response object - 200 Success - could be an empty list if no options have been added yet:

[
    {
        paymentOptionId: 123,        // Number: the payment option's ID
        paymentOptionLabel: "PayPal"  // String: the payment option's label
    },
    {
        // additional payment options to follow...
        // following the same structure...
    }
]

Response object - 404 Not Found, or 500 Server Error:

Flat descriptive message sent back without structure.

# 6. countries-and-regions endpoint

Request type: GET
Request endpoint: /countries-and-regions
Request parameters:

{ }

Response object - 200 Success:

[
    {
        countryId: 123,                // Number: the country's ID
        countryLabel: "South Africa",  // String: the label for the country
        provincesOrRegions: [
            {
                provinceOrRegionId: 456,               // Number: the ID of the province / region
                provinceOrRegionLabel: "Eastern Cape"  // String: the label for the province / region
            },
            {
                // additional provinces or regions to follow...
                // following the same structure...
            }
        ]
    },
    {
        // additional countries and regions to follow...
        // following the same structure...
    }
]

Response object - 400 Bad Request, or 404 Not Found:

Flat descriptive message sent back without structure.

# 7. shipping-quotes endpoint

Request type: POST
Request endpoint: /shipping-quotes
Request parameters:

{
    'productsCart': [
        {
            'productId': 2,           // Number: the ID of the selected product
            'productVariationId': 3,  // Number: the ID of the selected product variation
            'productQuantity': 1      // Number: the required quantity
        },
        {
            // additional products to follow...
            // following the same structure...
        }
	],
    'shippingAddressDetails': {
        'recipientName': 'John Smith',                // String: full recipient name
        'recipientEmailAddress': 'email@domain.com',  // String: email address of the recipient
        'addressLine1': '123 Sample Street',          // String: recipient address (line 1)
        'addressLine2': 'Sample Area',                // String: recipient address (line 2)
        'addressCityOrSuburb': 'Sample City',         // String: recipient's city
        'addressCountryId': 1,                        // Number: the selected country ID (see country / region endpoint above)
        'addressProvinceOrRegionId': 3876,            // Number: the selected province / region ID (see country / region endpoint above)
        'addressPostalCode': '1234'                   // String: the postal code for this particular address
    },
    'billingAddressDetails': {
        'recipientName': 'John Smith',                // String: full recipient name
        'recipientEmailAddress': 'email@domain.com',  // String: email address of the recipient
        'addressLine1': '123 Sample Street',          // String: recipient address (line 1)
        'addressLine2': 'Sample Area',                // String: recipient address (line 2)
        'addressCityOrSuburb': 'Sample City',         // String: recipient's city
        'addressCountryId': 1,                        // Number: the selected country ID (see country / region endpoint above)
        'addressProvinceOrRegionId': 3876,            // Number: the selected province / region ID (see country / region endpoint above)
        'addressPostalCode': '1234'                   // String: the postal code for this particular address
    }
}

Response object - 200 Success

{
    'products': [
        {
            'availableQuantity': 1,    // Number: an available quantity - this is a validation of the requested quantity against actual availability
            'productId': 2,            // Number: the product ID of the current product quoted for
            'productVariationId': 3,   // Number: the variation ID for this product combination
            'requiresShipping': true,  // Boolean: flag indicating whether or not shipping is required for this product
            'shippingOptions': [       // Array: collection of available carrier shipping options (could be empty if no options are available)
                {
                    'shippingCarrierId': 2,                   // Number: the ID of this carrier
                    'shippingCarrierLabel': 'FedEx',          // String: a label identifier for this particular carrier option
                    'shippingSingleItemRate': 1100.00         // Number: decimal indicating the rate for a single item
                    'shippingAdditionalItemRate': 1100.00,    // Number: decimal indicating the rate for additional items
                    'shippingItemFlatInclusiveRate': 100.00,  // Number: decimal indicating the flat inclusive rate
                    'shippingFinalAmount': 27600.00,          // Number: decimal indicating the final total shipping amount for this product
                },
                {
                    // additional product carrier options to follow...
                    // following the same structure...
                }
            ]
        },
        {
            // additional product shipping options to follow...
            // following the same structure...
        }
    ]
}

Response object - 400 Bad Request, or 404 Not Found:

Flat descriptive message sent back without structure.