×
 

Developer Zone

Developer Zone

  • Getting Started
  • Request your API Key
  • Overview & Documentation
  • Response Codes
  • Authentication
  • Methods
  • Samples
  • Request Limits
  • Request Limits FAQ

Getting Started with the Sage One API

The Sage One API is an interface for accessing Sage One data. The API also exposes a lot of the functionality available in Sage One.

Sage One customers can use the API to integrate with their existing websites and internal systems or the API can be used by 3rd party integrators to extend their own products or create new products using Sage One as the accounting engine.

To use the Sage One API, you will need to obtain an API Key to uniquely identify your application. To obtain this key, you will need to have a Sage One account.

1. Register for your Sage One account

2. Enrol as a developer and request your Sage One API key here.

3. Download and review the API Terms and Conditions

4. Integrate your application

Request your API Key

Simply fill in your details below and we will get back to you as soon as possible. Please note that API keys may take up to 2 working days to be issued.

 

Overview and documentation
To view the full API Specification click here

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: 1.1.1

All Calls require the API Key to be included as a query string parameter. This key will be issued by Pastel.

Any functions dealing with company specific data require the companyid 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 One developer forum if you get stuck.

Request Limits
All Sage One user accounts have a request limit of 5000 API requests per day. A maximum of 100 results will be returned for list methods, regardless of the parameter sent through.

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 servers discretion.

204

No Content

The call to the method was successful but there is not 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

Unauthorized

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 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 24 hours”. Your IP address will be blocked for 24 hours. It is advisable to make no more than one request per second to avoid this.

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.

In order for you to know the reason of the 429 status code, a header is added to the response. The header key is "X-RequestLimit-ExceededReason" with a value of either "LoginAttemptsExceeded" or "RateExceeded".

If you encounter a request limit, do not continue to make requests. Contact us on api@accounting.sageone.co.za so that your IP address can be unblocked.

500

Internal Sever Error

A server side error occurred.

503

Service Unavailable

The service is unavailable due to scheduled maintenance.

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

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

Here is an example:
Username: demo@pastelmybusiness.co.za
Password: Password123

Authorization header: Basic ZGVtb0BwYXN0ZWxteW1vbmV5LmNvLnphOlBhc3N3b3JkMTIz


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 Orderby 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:

  1. http://[API URL]/api/[ver]/customer/Get?$skip=2&$top=20&$orderby=ID&apikey=39478ac6-ac2a-44d8-a31c-7e7e14af4de3& companyid=1
  2. 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:

  1. http://[API URL]/api/[ver]/Customer/Get?$skip=2&$top=20&apikey=39478ac6-ac2a-44d8-a31c-7e7e14af4de3& companyid=1
  2. 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.

Samples
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 = "xx@xx.co.za";
            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 / JqQuery 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
            }
        });
    }

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 } }); }"

Request limits

Requests per minute

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.

Request limit FAQ

What if I need more than 100 calls a minute?
Quite often, applications that you might believe would exceed the usage limits, can in fact work within the limits by analysing how the API is being utilized.

A local data cache can be maintained and synchronised using the various OData calls available together with the Modified and Created properties available in the API.

It is also recommended that requests be queued so that limits are locally enforced.

What is the best way to handle requests on my side?
It is recommended that applications queue requests to the Sage One API. This will allow you to ensure requests are within the supported limits, and will also allow your application to function even in the event that it cannot reach the Sage One API temporarily.

What if I need to retrieve large amounts of data from Sage One?
One function which can cause an application to exceed the usage limits is extracting data from Sage One.

Although a default paging limit of 100 is applied to all API keys, this limit can be adjusted reducing the number of calls required to retrieve data.

Does my application only have 100 requests per minute for all my users?
No, limits are per user and per company, if multiple users are making use of your application limits are handled accordingly.

What if my application still cannot function correctly within the API Usage Limits?
While the current API limits are not flexible, we can advise on making calls more efficient. Click here ('click here' must open up an e-mail which must be sent to: api@accounting.sageone.co.za) to contact us.

Contact us

Any queries? Simply click here