Stephen Smith's Blog

Musings on Machine Learning…

Sage 300c Web Services

with 16 comments


Hand in hand with true HTML/JavaScript/CSS Web UI’s you also want to access the same logic from other general programs using RESTful Web Services. This gives a general API to access the application which doesn’t require any Sage 300 components be installed on the client computer and doesn’t require the calling application be on the same computer or even at the same location.

ASP.Net MVC Web screens tend to have quite quickly changing interfaces between the Views, Controllers and Models which makes using then same Web Services as the UI a bit problematic, especially as the screens evolve quickly. You want a stable Web Services interface that preserves compatibility from version to version and provides a wider more general interface. At the same time the developer of an ASP.Net MVC program doesn’t want to do a completely different implementation for exposing Web Services.

The way ASP.Net MVC solves this dilemma is by allowing you to add a Web Services stack on top of your existing models (which in our case means fully leveraging the business repositories and Sage 300 Business Logic as well). But it uses a custom controller to handle the Web Services requests. In the Microsoft stack there are several supported standards for Web Services, but the one we used is OData. This means that using our Web Services you can do all the standard OData queries and supports the standard OData meta-data.

With our Sage 300 2016 Product Update 1 we have included a number of Web Services in the product. These are automatically installed if you select the Web UIs option from the main installation. So if the Web UIs are up and running then you can try playing with the Web Services. In this article we’ll show how to get started using these. Over next couple of releases, we’ll be fleshing these out to support all the Business logic as well as services beyond the basic CRUD operations.

Some Examples

If you type:


into the Chrome browser you will be prompted for your Sage 300 login credentials, which you can enter. Note that from this browser prompt the password is case sensitive, so you need to uppercase your normal Sage 300 password (since our regular login screen normally does this).


Then after entering the correct data you will get back a JSON object with all the information in your chart of Accounts (including details like optional fields):


Working with the Browser directly, although fun, will soon become tedious. Another easier approach is to install the Chrome add-in PostMan which will remember your Web Services so you can adjust and repeat them. You need to set the Basic Authorization header with your Sage 300 login and password. Below we use the shortened URL to get the list of all the available feeds for SAMLTD with the URL:


using PostMan:


And we get the returned JSON object containing the list of Web Services we support. It by company since not all accounting application may be activated in the database.


You can do standard OData queries to filter the returned data. For instance:

https://yourservername/Sage300webapi/sdata/-/SAMLTD/GL/Accounts?$filter=UnformattedAccount eq ‘1020’

will result in just this one account being returned:


The way we implement queries is via adding LINQ support that will convert the LINQ query to a Browse filter for our Sage 300 View. This means we will support any query as long as we can translated it into a Browse filter. If the filter contains a SQL function we don’t support, then you will get back a not supported error for your query. Note that often people writing code for the regular Web UIs just use our C# LINQ support to browse/fetch rather than calling browse/fetch directly since this lets you leverage other advanced features in C# and .Net.

Other Clauses

You can specify a sort order as long as what you requests matches an index in the Sage 300 database:

https://yourservername/Sage300webapi/sdata/-/SAMLTD/GL/Accounts?$orderby=UnformattedAccount desc


You can specify to get the top n records or to skip n records via:



which is useful to page data.

Meta Data

You can get meta data for all the feeds using the $metadata tag. For instance:


will return the meta data for all the feeds that are relevant for SAMLTD:


(Note that this is quite a large JSON object to process).


This initial implementation includes sufficient G/L feeds for supporting financial reporting. Hence these G/L feeds are read only at this point. We do support inserting G/L Batches, O/E Orders and A/R Customers. Many of the non-G/L feeds support updating, inserting and deleting. If the entity supports these then you can delete the record by specifying DELETE as the HTTP verb (which is easy in PostMan), similarly insert if via POST and update if via PUT or PATCH.

Generally, the best way to figure out the format of the payload to include with these is to do a GET and then use that payload as a template to build the JSON object with the data you want to update or insert.

Since these Web APIs are built on the Sage 300 Business Logic all the usual validation will take place and you will get back Sage 300 error messages in the response payload if the request fails.


Ideally the responses from the server will include error messages to tell you what went wrong, so always check these. If they aren’t helpful, then on your web server check the Web API trace log which is located at:


This will usually have the raw error when something has gone wrong.

If you don’t see anything in either of these places, perhaps check your IIS log to make sure that the request didn’t get rejected for some other reason. Especially remember to include your basic authorization header.


If you expose your Web Services to the general Internet, ensure that you follow all the security measures in this article. You will need to do this if you are integrating with an external cloud service or other client located outside your network. Generally, you want to keep your Web Service communications private, so they can’t be accessed by hackers or spied on by hackers. Using good practices around enforcing HTTPS is crucial here.


The set of Web Services included in the Sage 300 2016 Product Update 1 are intended to support Financial Reporting on General Ledger as well as basic e-Commerce functionality like accessing Customers and entering Orders. Part of the intent of this release is to let people play with these and provide feedback as we move to complete out the full set of Web Services for our next version.

Written by smist08

February 15, 2016 at 11:26 pm

16 Responses

Subscribe to comments with RSS.

  1. […] Sage 300c Web Services  […]

  2. Hi Stephen,

    Do you have any document about how to install and configure webui? I tried to install webui, but never can get it works. When I configure portal database, I always get some service errors. And I cannot find any Sage service installed in my environment.


    February 19, 2016 at 3:00 pm

  3. Stephen,
    Thank you for providing great examples on interfacing with Sage 300. My question though is if Sage 100 has the same RESTful WebApi/sData or .Net API interface and if so I’m having some difficulty finding documentation; it seems like everything points to Sage 300. Would you know of any resources providing good examples for the Sage 100 platform outside of the DPP.

    Thank you,

    Sean Gahan

    Sean and Gahan

    April 22, 2016 at 10:22 pm

  4. Hi Stephen,
    Such a wonderful Blog. Was really helpful.
    I got all the OrderEntries using a GET method, and was trying to edit one OrderEntry.
    Is edit/create/delete of OrderEntry Supported by Sage?
    If yes, can you please let me know how to do it?
    If it is not supported by Sage, can you please let me know how to do the same for G/L or A/R?
    Thanking you in anticipation.



    June 6, 2016 at 4:22 am

    • You should be able to insert a new order by providing the order payload with an HTTP POST verb. You may be able to delete an order using the DELETE verb (but I’m not 100% sure). You can’t update an existing order. For many other documents you can use the PUT verb to do an update.


      June 6, 2016 at 6:34 pm

    • Rohith,
      I’m using Sage 100 and can GET from a remote domain (my workstation in my network) but I can only edit or create records if the source/project is running on the same server as the SData web endpoint; eg, my webAPI running as a virtual directory under the SData website and referencing SData resources via localhost. So the request url would look like this:

      and the request header would look something like this:
      PUT /SData/MasApp/MasContract/COMPANYXYZ/SO_SalesOrderHeader(‘0003001’) HTTP/1.1
      Host: localhost
      Connection: keep-alive
      Content-Length: 703
      Authorization: Basic U0RhdGE6MXFhenhzdzI=
      Origin: http://localhost
      User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
      Content-Type: application/atom+xml;type=entry
      Accept: */*
      X-Requested-With: XMLHttpRequest
      Referer: http://localhost/MySDataVirtualDirectoryWebAPI/test.htm
      Accept-Encoding: gzip, deflate, sdch
      Accept-Language: en-US,en;q=0.8

      I believe this may be a security feature in Sage or it could be CORS, but since there is no documentation I can only guess. One might ask if SData can be updated via a remote domain. Best of luck.

      Sean and Gahan

      June 6, 2016 at 7:09 pm

      • True the details vary by product. Sage 300 can do updates and deletes either through the older SData services or the newer Sage 300c web services. As long as you don’t reference a third computer, CORS shouldn’t be a problem.


        June 7, 2016 at 2:24 am

      • Thanks for the fast reply guys.
        I am using Sage300 2016 and I can make a GET REST call to http://localhost/Sage300webapi/sdata/-/SAMINC/OE/OrderEntries to get all orders where each order has almost 300 fields.

        So now I need to change one field of the order. So i am selecting the order, changing the value of that filed and then need to PUT it back. I understand. But what would be the url to PUT? Do i need to all that 300 field order in the request Header? Or is there a way in which I can say, where orderNumber=OR00000001, set XXX=”abc”?

        I have the same question about the delete and create function as well, even though it doesn’t work for Orders, would be good to know the same in other modules

        My Code is as below:

        HttpClient client = new HttpClient();
        public String getOrders()
        using (client)
        client.BaseAddress = new Uri(“http://localhost/Sage300webapi/”);
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));
        var byteArray = Encoding.ASCII.GetBytes(“ADMIN:ADMIN”);
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“Basic”, Convert.ToBase64String(byteArray));

        HttpResponseMessage response = client.GetAsync(“sdata/-/SAMINC/OE/OrderEntries”).Result;
        if (response.IsSuccessStatusCode)
        var responseContent = response.Content;
        // by calling .Result you are synchronously reading the result
        return responseContent.ReadAsStringAsync().Result;
        return null;

        If you could give me an edit and delete order or G/L or A/R modules, I really appreciate that and would be a life savior.


        June 7, 2016 at 6:01 am

      • Rohith,
        Once again, I’m using Sage 100 so it may be a bit different, but I can pass in the specific field that I wish to update. Not sure if this is the same with Sage 300, but I’m sure Stephen can answer that one. By the way Stephen has a great video that may answer some of your questions: .

        Best regards,


        Sean and Gahan

        June 7, 2016 at 3:14 pm

  5. Rohith,
    One last thing, make sure the “Content-Type” = “application/atom+xml;type=entry” . Make sure to add that to your header.

    Best regards,


    Sean and Gahan

    June 7, 2016 at 3:46 pm

    • The Sage 300c Web API you are using does use JSON for its payloads. Unfortuneately updating documents with details isn’t supported yet, I think your only option with this API is to try deleting it and then re-inserting it. This will give it a new order number though. The only real option to actually update an order is to use the .Net or COM APIs, but even there there will be restrictions depending on the order status (like whether its shipped, invoiced, etc.).


      June 7, 2016 at 4:38 pm

      • Excellent point; Sage 100 only supports SData 1.0, so it’s payload is XML.

        Sean and Gahan

        June 7, 2016 at 4:53 pm

  6. Hi Stephen, we’ve been told that support for sdata is being discontinued and one of our vendors suggest they develop web services using the COM API. We want to build a consumer web site and mobile (android/ios) apps which will require Json/Restful services to the Sage 300 accpac server. This article suggests that web services are still being developed and enhanced over the (older) sdata services. Is this true?


    July 8, 2016 at 12:38 am

    • I don’t know when the support for SData will be fully dropped, but the future are the new Restfull web services described in this article. You should see this set of web services become much more complete in the next Sage 300 release.


      July 8, 2016 at 4:46 pm

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: