Complete Guide: Using the Web API
This guide is a step-by-step walkthrough for connecting an external system (your website, your own app, a middleware, another piece of software) to the AdmCloud Web API: how to authorize API usage by creating an Integration, how to authenticate with basic authentication or with a token, how to make your first call from Swagger or another tool, ready-to-copy code samples, how to read the response and where the full documentation for every object lives.
What the Web API is and what it's for
The AdmCloud Web API is a REST API that exposes, over HTTPS and in JSON, almost everything you can do from the web screens: read and create customers, vendors, items, GL accounts, invoices, quotes, sales orders, purchase orders, receptions, deposits, journal entries, payroll and much more. That way an external system can read from and write to your company without a person having to log into the application.
The production base address is https://api.admcloud.net/api/, and each object has its own
route. For example, listing customers is:
GET https://api.admcloud.net/api/Customers?skip=0&company=MyCompanyDB&role=Administrators&appid=00000000-0000-0000-0000-000000000000
Every operation returns the same response envelope: a JSON object with
success (whether the operation worked), message (the error message when
it fails) and data (the result: a list, a document, an identifier...). This is
explained in detail below, under Reading the response.
Before you start: what to have at hand
- A plan that includes the API: Basic or higher (not available on Billing or Start).
- The Customization permission in your user group, so you can create the Integration.
- A real AdmCloud user and password: the API has no standalone keys; it always authenticates as a user of the company.
- Your company's database name (the
companyparameter). You can see it on the Web Services Integrations screen, in the Database Name field. - The name of the user group the calls will run as (the
roleparameter; for example Administrators). - The Integration ID (the
appidparameter), which you get in step 1.
Step 1: create the Integration that authorizes API usage
Before your first call you must authorize in the system the program that will consume the API. You do that by creating an Integration: AdmCloud assigns it a unique identifier (the appid) that travels with every call, so each connected system is identified and can be switched off independently whenever you want.
- Go to Web Services Integrations (Customization / System Administration menu) and click New Integration.
- Enter a descriptive Name identifying the system that will use it (for example, "Order website" or "Branch point-of-sale integration"). The name is required and can't be duplicated.
- Decide whether the integration should Execute as Administrator (see the warning below) and use Notes to record what it's for and who requested it.
- Save. AdmCloud generates the Integration ID (the appid), which can no longer be changed.
- Open the details of the integration you just created. There you'll find the appid, the database name and a list of ready-made sample URLs for the most used objects (Customers, Vendors, Items, Accounts, Invoices, Purchase Orders, Deposits, Journal Entries, etc.). It's the fastest way to test: copy a URL and open it in your browser.
| Integration field | What it's for |
|---|---|
| Name | Identifies the integration. Required and unique. |
| Integration ID (appid) | The identifier you'll send on every call. AdmCloud generates it on save and it can't be edited. |
| Disabled | Kill switch: turning it on makes every call using that appid stop working immediately, without deleting the integration or losing its history. |
| Execute as Administrator | When on (the default), calls with that appid run with full access, without validating the permissions of the authenticated user. Turn it off and every call respects the user's real permissions and group, exactly as in the web screens. |
| Notes | Free text to document the integration's purpose. Only internal users see it. |
The appid does not replace the user and password. It's an additional piece of data that travels alongside the credentials, not instead of them. And be careful with Execute as Administrator: while it's on, the integration bypasses the user's permissions. Turn it off when you want the integration to do exactly what that user could do inside the application.
Create one integration per system, not a single one for everything. That way you can disable or audit one connection without affecting the others. The fields and validations are covered in more detail on the Web Services Integrations (API) page.
Step 2: basic authentication (the simplest way)
Basic authentication (the HTTP standard) is the most direct way to call the API: on
every call you send the user's email and password in the Authorization header, and the
context data (company, group and integration) as parameters in the address.
- Header:
Authorization: Basic <email:password in Base64>. Almost every tool and library builds it for you: you just type the user and password. companyparameter: the company's database name. It tells the API which company to work on.roleparameter: the name of the user group the call runs as (orroleidif you prefer to send its identifier).appidparameter: the ID of the Integration created in step 1.
A complete call looks like this:
GET https://api.admcloud.net/api/Customers?skip=0&company=MyCompanyDB&role=Administrators&appid=8f3c1e42-...-9b21
Authorization: Basic dXNlckBjb21wYW55LmNvbTpNeVBhc3N3b3Jk
When the call comes in, AdmCloud validates, in this order:
- That the email and password are correct and the account isn't blocked.
- That the user exists in the company given in
company. - That the user group given in
role(orroleid) is actually assigned to that user. - That the Integration for the
appidexists and isn't marked as Disabled. - That the user has the privilege required for the operation... unless the integration is set to Execute as Administrator, in which case this step is skipped.
Always send role (or roleid). Without it the call isn't
tied to any user group and will fail with "Unauthorized" as soon as privileges are validated —
that is, on any integration that isn't set to Execute as Administrator.
If authentication fails, the API responds 401. When the reason is specific (wrong
password, blocked account, company mismatch), the response body carries the real message in
message so you can surface it in your system.
Step 3: token authentication
The alternative is to authenticate once and then use a token. The token is a signed
string that already carries the session context inside (user, company, group, subsidiary and
location), so subsequent calls don't send the password again: the token parameter is
enough. This is the recommended option when your system makes many calls in a row or when you don't
want the password travelling on every request.
-
(Optional) Find the user's companies. Using basic authentication and
without the
companyparameter, callPOST /api/Login/GetCompanies. It returns the user's companies, ordered by last login, with their identifier and database name. -
Find the user group identifier (
RoleID). You can get it by callingPOST /api/Login/SelectCompany?CompanyID=..., which returns the user's available groups in that company; or take it from the identifier shown in the address when you open the group under User Groups inside the application. -
Generate the token using basic authentication:
The response carries the token in thePOST https://api.admcloud.net/api/Token?Company=MyCompanyDB&RoleID=1c9a...&appid=8f3c1e42-...-9b21 Authorization: Basic dXNlckBjb21wYW55LmNvbTpNeVBhc3N3b3Jkdatafield. -
Use the token on the remaining calls, as the
tokenparameter and with no authentication header:GET https://api.admcloud.net/api/Customers?skip=0&token=eyJhbGciOi...
| Basic authentication | Token | |
|---|---|---|
| What you send on each call | User and password + company, role and appid | Only token |
| When to use it | One-off calls, testing, simple scripts | Systems making many calls or keeping a session |
| Permissions | May bypass privilege validation if the Integration is set to Execute as Administrator | The user's and group's real privileges are always validated |
| Context (company, group, subsidiary) | Given as parameters on each call | Baked into the token when it was generated |
When you call with token, the appid isn't sent, so
"Execute as Administrator" does not apply: the call always respects the
permissions of the user group the token was generated with. If an operation works with basic
authentication but fails with a token saying "Unauthorized", it's almost always because that
group is missing the privilege.
The token expires. Your system should be ready to generate it again (repeating step 3) once calls start being rejected for an invalid or expired token.
Step 4: making your first call with Swagger or another tool
You don't need to write code to try the API. The recommended way is Swagger, the interactive documentation that also executes the calls:
- Open https://api.admcloud.net/ApiDocumentation/ (inside the application, the same link is in the information notice on the Integrations screen).
- At the top there's a module selector. Since the API exposes close to a thousand operations, the documentation is split into one document per module (General, Accounts Payable, Accounts Receivable, Banking, General Ledger, Inventory, Payroll, Point of Sale, System Administration, etc.). Pick the module of the object you're after.
-
Expand the operation you want to try (for example
GET /api/Customers) and click Try it out. -
Fill in the parameters:
skipas 0,companywith your database name,rolewith your user group name andappidwith the integration ID. Then execute. - The first time, the browser will ask for user and password (the standard basic authentication dialog that appears on the 401). Enter your AdmCloud email and password; the browser reuses them on later calls.
-
Check the response body. If
successistrue, you're consuming the API correctly.
Other equally valid tools:
- The browser, plain and simple: copy one of the sample URLs from your Integration's details and open it. The browser will ask for user and password and show you the JSON.
- The API Explorer (apiexplorer.admcloud.net): a dedicated interface to browse the available objects and their parameters.
- Postman, Insomnia or similar: create the request, pick Basic Auth in the authorization tab and enter your email and password; add
company,roleandappidas query parameters. - curl, from a terminal (see the sample below).
The API only serves calls made to its published addresses (api.admcloud.net and the
internal test environments). If you build the URL with any other domain, the request is rejected
with 401 even when the credentials are correct.
Step 5: a simple code sample
The three samples do the same thing: list the first customers using basic authentication. Replace the email, password, database name, group and appid with your own.
curl
curl -u "user@company.com:MyPassword" \
"https://api.admcloud.net/api/Customers?skip=0&company=MyCompanyDB&role=Administrators&appid=8f3c1e42-...-9b21"
C#
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
const string EMAIL = "user@company.com";
const string PASSWORD = "MyPassword";
const string COMPANY = "MyCompanyDB";
const string ROLE = "Administrators";
const string APPID = "8f3c1e42-...-9b21";
using (var client = new HttpClient())
{
var credentials = Convert.ToBase64String(
Encoding.UTF8.GetBytes(EMAIL + ":" + PASSWORD));
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic", credentials);
var url = "https://api.admcloud.net/api/Customers"
+ "?skip=0"
+ "&company=" + COMPANY
+ "&role=" + ROLE
+ "&appid=" + APPID;
var response = await client.GetAsync(url);
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
}
}
}
JavaScript
const EMAIL = "user@company.com";
const PASSWORD = "MyPassword";
const COMPANY = "MyCompanyDB";
const ROLE = "Administrators";
const APPID = "8f3c1e42-...-9b21";
const url = "https://api.admcloud.net/api/Customers"
+ "?skip=0&company=" + COMPANY + "&role=" + ROLE + "&appid=" + APPID;
const response = await fetch(url, {
method: "GET",
headers: {
"Authorization": "Basic " + btoa(EMAIL + ":" + PASSWORD)
}
});
const result = await response.json();
if (result.success) {
console.log(result.data);
} else {
console.error(result.message);
}
Creating a record is just as simple: use POST against the same route, with the object
in the request body as JSON. The response carries the new record's identifier in data:
curl -u "user@company.com:MyPassword" \
-H "Content-Type: application/json" \
-d '{ "Name": "Test customer", "Customer": true }' \
"https://api.admcloud.net/api/Customers?company=MyCompanyDB&role=Administrators&appid=8f3c1e42-...-9b21"
Never put the user and password in code that runs in the end user's browser (a public page, a distributed desktop app). In those cases your own server should be the one calling the API, keeping the credentials out of the end user's reach. The JavaScript sample above is for server-side code or local testing.
The C# sample repository has complete, working projects for several objects, and the walkthrough video covers the whole process on screen.
Reading the response and paging
Every operation responds with the same structure:
{
"success": true,
"message": null,
"data": [ ... ]
}
| Field | What it holds |
|---|---|
success | true if the operation ran correctly; false if it failed. |
message | The error message when success is false. Empty or null when everything went fine. |
data | The result: a list, a full document, the identifier (GUID) of the created record, etc., depending on the operation. |
A business error does not arrive as an HTTP error. If the document fails a
validation, the response is still 200 but with success: false and
the detail in message. Your system must always check success, not just
the HTTP status code.
Lists are paged: they return at most 50 records per call. To walk
through everything, keep increasing the skip parameter (0, 50, 100, ...) until a call
returns an empty list.
Where the API documentation lives
All of these resources are linked from the information notice on the Web Services Integrations screen and also from each integration's details:
| Resource | What you'll find |
|---|---|
| Swagger documentation | The complete, executable technical reference: every operation grouped by module, each parameter with its type and whether it's required, the body structure of each document and a button to run the call live. This is the official source. |
| API Explorer | A tool for browsing the available objects and building calls in a guided way. |
| Walkthrough video | The full run-through on screen: creating the integration, authenticating and making the first call. |
| C# sample code | Sample projects ready to build and run. |
| Your Integration's details | Sample URLs already built with your appid and your database, for the most used objects. The quickest shortcut for a first test. |
From inside the application you can also open the documentation at the
/ApiDocumentation address, which takes you to the same Swagger page.
Security best practices
- Use a dedicated API user, not a person's personal account. When creating the user you can flag it as Only for API: it then can't sign into the web application and its password won't expire, which prevents an integration from breaking overnight.
- Give that user a group with the minimum permissions needed and turn off Execute as Administrator on the integration, so the API can't do more than that group allows.
- One integration per connected system, with notes explaining its purpose.
- Disable the integration as soon as a system stops being used or you notice odd activity; it's immediate, reversible and keeps the history.
- Keep credentials server-side, never in code downloaded to the end user's browser.
- Always call over HTTPS to the API's published addresses.
Tips and common mistakes
I get a 401 with no message. A valid authentication method is missing: you didn't
send the Authorization header, nor token, nor appid; or the
address you're calling isn't one of the API's published ones. Also check that the header uses the
Basic scheme.
The response says the integration doesn't exist. The appid was copied wrong, belongs to another company, or the integration is marked as Disabled. Confirm it in the integration's details.
The response says "Unauthorized". The credentials are fine, but the user group is
missing the operation's privilege (for example, add permission over Customers), or you didn't send
the role parameter and the call ended up with no group attached.
The user isn't found in the company. The value in company must be
the database name (the one shown on the Integrations screen), not the company's
trade name. And the user must exist in that company with the same email.
Always try a simple GET first (Customers or Items, say) before attempting to create documents. If the GET works, authentication, company, group and integration are all settled, and any later error will be about the data you're sending.