search icon
Header b7

Become a Sage Business Cloud Accounting Developer

Connect your app or develop add-ons through our API.

How do I get started?

1. Sign up

2. Obtain your key

Request your own Accounting API Key to get access. 

3. Terms and Conditions

Download and review our API Terms and Conditions.

4. Integration

Integrate your application!

API Overview

Here's the basics to get you started.

Format

The current supported format is JSON.

URL Structure

The service URLs are built up as follows:
[API URL]/api/[ver]/[service name]/[method name]/[ID (when required)]?[required query string parameters]

API Url: https://accounting.sageone.co.za

Current Version: 2.00

All Calls require the API Key to be included as a query string parameter. This key will be issued by Sage Accounting.
Any functions dealing with company-specific data require the company id parameter.

URL Examples:

Company Get List Example:
http://[API URL]/api/[ver]/Company/Get?apikey={39478ac6-ac2a-44d8-a31c-7e7e14af4de3}

Individual Company Get Example:
http://[API URL]/api/[ver]/Company/Get/1?apikey={39478ac6-ac2a-44d8-a31c-7e7e14af4de3}

Individual Customer Get Example:
http://[API URL]/api/[ver]/Customer/Get/1?apikey={39478ac6-ac2a-44d8-a31c-7e7e14af4de3}&CompanyId=1

Services

There are over 100 API services. Please refer to the API Specification and ask the Sage Accounting developer forum if you get stuck.

Request Limits

All Sage Accounting companies have a request limit of 5000 API requests per day. A maximum of 100 API results per minute will be returned for list methods, regardless of the parameter sent through.

 

API Response Codes

HTTP Code Description  Occurs When: 
200 OK Everything performs as expected.
201  Created A new entity has been created.
202 Accepted The call to the method was accepted and will be handled at the server's discretion.
204 No content The call to the method was successful but there is no data that this method will return.
400 Bad request A malformed request was sent through or when a validation rule failed. Validation messages will be returned in the response body.
401 Unauthorised The user is not correctly authenticated and the call requires authentication. The user does not have access rights for this method.
404 Not found The requested entity was not found. Entities are bound to companies. Ensure the entity belongs to the company.
405 Method not allowed HTTP Verb is not specified or an incorrect verb is used.
Or the user does not have access to the specified method. This applies to invited users.
409 Conflict When attempting to delete an item that is currently in use.
415 Incorrect or missing content-type header A valid Content-Type header such as application/json is required on all requests.
429 Request limit reached
The limit of 100 requests per minute per company is exceeded or more there are more than 20 failed login attempts.

Request Limits

A limit of 100 requests can be made per minute per company. If this request limit is exceeded, the API will return HTTP 429 (Request Limit Reached) with the message “Your IP address has exceeded the allowed number of transactions per minute and has been blocked for 1 hour”. Your IP address will be blocked for 1 hour. It is advisable to make no more than one request per second to avoid this.

Failed login attempts

A limit of 20 failed login attempts can be made per hour through the API. If this request limit is exceeded, the API will return HTTP 429 (Request Limit Reached) with the message “Your Username has exceeded the allowed number of login attempts and has been blocked for 24 hours”. The Username will be blocked for 24 hours.

Encountering a rate limit

Accounts are temporarily blocked if a request limit is exceeded. Accounts will be blocked based on the API Key, Company Id and User. Being blocked in one company will not block you from making calls in other companies.

Accounts are automatically unblocked within an hour. Do not continue to make requests as this may extended the blocking period.

If you encounter a limit, do not continue to make requests as this may extend the blocking period. Queue Requests until the block is lifted.

500 Internal Server Error A server-side error occurred.
503 Service unavailable The service is unavailable due to scheduled maintenance.

API Authentication

This API uses basic webforms authentication. To authenticate a user prior to calling a method, you will need to add a standard HTTP authorization header to the request.

This will require the username and password, separated by a colon(:) and Base64 encoded.

Here is an example:

Username: [email protected]

Password: Password123

Authorization header: Basic ZGVtb0BwYXN0ZWxteW1vbmV5LmNvLnphOlBhc3N3b3JkMTIz

 

API Methods

Save Methods

The save method requires that the request body contains the entity in JSON (XML is not currently supported).

Once validation has been completed, and the entity have been saved, the entity is returned and the new location url is specified as a response header.

Get Methods

Result limit of 100 applies to all queryable methods.

Get() method calls support a subset of the OData protocol.

Supported functions are listed below.

For example, the following Url returns the first three products, ordered by name:
http://[API URL]/api/[ver]/products?$top=3&$orderby=Name

NOTE: 
Filter and Order by will not work for string values of any kind. Specific methods are exposed to allow querying on string values where applicable.

Pagination

All arrays of objects that get returned are wrapped with the total count for the relevant query and the number of returned results in the current call.

The Get methods support pagination by using the skip and top key works in the url. If no default order clause is specified, you will need to provide one.

Examples of call where you supply the sort order:
http://[API URL]/api/[ver]/customer/Get?$skip=2&$top=20&$orderby=ID&apikey=39478ac6-ac2a-44d8-a31c-7e7e14af4de3& companyid=1

http://[API URL]/api/[ver]/customer/Get?$skip=40&$top=2&$orderby=ID&apikey=39478ac6-ac2a-44d8-a31c-7e7e14af4de3& companyid=1 

Examples of call without the sort order:
http://[API URL]/api/[ver]/Customer/Get?$skip=2&$top=20&apikey=39478ac6-ac2a-44d8-a31c-7e7e14af4de3& companyid=1

http://[API URL]/api/[ver]/Customer/Get?$skip=40&$top=2&apikey=39478ac6-ac2a-44d8-a31c-7e7e14af4de3&companyid=1

Delete Methods

Delete operation will only be allowed if no other item/entity or transaction is making use of the item trying to be deleted.

API Samples

Please note that these samples cannot be used as they are not suitable for production code.

C# Sample
//NB: This is not production Code
static void Main(string[] args)
{
    string baseUrl = "http://[API URL]/api/[ver]/";

    string apikey = "xxx-xxx";
    int companyId = 0;
    string userName = "[email protected]";
    string password = "xx";

    var requestUrl = baseUrl + "customer/get?APIKey=" + apikey + "&companyid=" + companyId;

    var req = WebRequest.Create(requestUrl);

    //Option 1 to authenticate 
    req.Credentials = new NetworkCredential(userName, password);

    //Option 2 to authenticate 
    //string encodedCredentials;
    //encodedCredentials = Convert.ToBase64String(Encoding.ASCII.GetBytes(myBusinessUserName + ":" + myBusinessPassword));
    //req.Headers.Add("Authorization", "Basic " + encodedCredentials);

    req.Method = "GET";

    try
    {
        var response = req.GetResponse();

        if (response != null)
        {
            var responseStream = response.GetResponseStream();
            if (responseStream != null)
            {
                var resultString = new StreamReader(responseStream).ReadToEnd();

                var retrievedData = "Data: " + resultString + Environment.NewLine;
                Console.WriteLine(retrievedData);
            }
        }
    }
    catch (WebException ex)
    {
        HttpWebResponse errorResponse = ex.Response as HttpWebResponse;
        Console.WriteLine("StatusCode: " + errorResponse.StatusCode);
        Console.WriteLine("StatusMessage: " + errorResponse.StatusDescription);
    }
    Console.Read();
}

 

Javascript / jQuery Sample

var baseUrl = 'http://[API URL]/api/[ver]/';

function getAuthorisation() {
    return "Basic " + $.base64Encode($('#txtUsername').val() + ":" + $('#txtPassword').val());
}

function getCompanyId() {
    return $('#txtCompanyId').val();
}

function getAPIKey() {
    return $('#txtApiKey').val();
}

function GetTransactions() {
    $.support.cors = true;

    $.ajax({
        type: "GET",
        contentType: "application/json; charset=utf-8",
        url: baseUrl + "/customer/Get?apikey=" + getAPIKey() + "&companyid=" +
             getCompanyId(),
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Authorization", getAuthorisation());
        },
        success: function (data) {
            //Do something
        },
        error: function (data) {
            //Do something else
        }
    });
}