OAuth 2.0 authorization
Sage Intacct uses the OAuth 2.0 authorization standard to allow REST API clients to obtain secure access to our web services on behalf of specific resource owners. Client applications can use the authorization code or the client credentials grant type depending on the type of access required. Client applications can also use the proof key for code exchange (PKCE) flow, with the authorization code grant type, for mobile apps and public clients where storing the client secret is unsafe.
Use the OAuth 2.0 authorization code or the client credentials grant type to obtain an access token, then include it in REST API requests to access your company's data. The tokens generated by Sage Intacct are JSON Web Tokens (JWT). JWT tokens are designed for securely exchanging information encoded as JSON objects. They contain the ID of the currently logged-in user, the company ID, and other required information. You can examine the components of your access token by visiting JWT.
The company to which you will be sending API requests must authorize your sender ID. You can either add your web sender ID to the Company Security tab or log in as an admin user when approving the OAuth authorization request.
Authorization code grant type
The authorization code grant type is supported for applications in which a user can click a button or link to grant the application access to their data in Sage Intacct. The OAuth 2.0 authorization code flow involves the following steps:
- The user signs into your application and clicks a link to authorize your application to access their Sage Intacct data.
- A Sage Intacct log in screen is displayed and the user logs in.
- The user is prompted to grant your application access to their data and must click Accept .
- The authentication server responds by redirecting the user to the registered callback URI with an authorization code in the query string.
- Your application captures the authorization code and uses it to request an access token.
- Your application receives the access token and includes it in the headers of all requests to the REST API.
Authorization code request
To request an authorization code, send a GET request to the following endpoint with the listed parameters:
Endpoint: https://api.intacct.com/ia/api/v1/oauth2/authorize
Parameter |
Value |
---|---|
response_type |
code |
client_id |
Your application's client ID |
redirect_uri |
The redirect URI set for your application in the Sage App Registry |
state |
A random value to use to validate the response |
scope |
Use offline_access if you want to get a refresh token in addition to an access token |
Sample authorization code request:
https://api.intacct.com/ia/api/v1/oauth2/authorize?response_type=code&client_id=*********&redirect_uri=https://mysite.com/callback.php&state=123456&scope=offline_access
Sample redirect URI response with code
and state
in query string:
https://mysite.com/callback.php?code=g0ZGZmNjVmOWIjNTk2NTk4ZTYyZGI3&state=123456
Validate that the response is authentic by verifying that the state
value matches the value sent in the request. Extract the authorization code
from the response, then include it in a request for an access token.
Access token request
To request an access token, send a POST request to the following endpoint with the listed parameters:
https://api.intacct.com/ia/api/v1/oauth2/token
Parameter |
Value |
---|---|
grant_type |
authorization_code |
code |
The authorization code from the previous response |
redirect_uri |
The redirect URI set for your application in the Sage App Registry |
client_id |
Your application's client ID |
client_secret |
Your application's client secret |
Sample access token request:
curl --location --request POST 'https://api.intacct.com/api/v1/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6IjkyZDRkY2Y0MTRlNmEyYzNkNzhkLlNhZ2VfSW50YWNjdF9VSS5hcHAuc2FnZS5jb20iLCJjbnlJZCI6Im9hdXRoMiIsImF1dGh6Q29kZSI6IjQ2MTkyMTYxNGZmMTM5ODcwMWQxY2UzOTdjZjI5M2M3ZWUwNDY5MjUiLCJ1c2VySWQiOiJBZG1pbiJ9.49P6x_nOqwTe5_Cr-MiMYTI2q9KOsvlyIGzTQgk7nc4' \
--data-urlencode 'redirect_uri=https://mysite.com/callback.php' \
--data-urlencode 'client_id=*********' \
--data-urlencode 'client_secret=*********'
Sample response, if a refresh token was requested in the authorization code request:
{
"token_type": "Bearer",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImI1OTc0YjZjNWQ2ZjJmMWVkYjg0LmFwcC5zYWdlLmNvbSIsImNueUlkIjoiR2FyZGVyIFN1cHBsaWVzIiwiYXV0aHpDb2RlIjoiZWIxYTRlZTBiMjVjNjgyYjJkZmMzNzg5OTcxNzFmYmJhYmE2NDA4NyIsInVzZXJJZCI6ImRhaXN5LmJsdWUifQ.9uMW6BqnYNTbS3x7XYSSU1rq_jxi29F7FfWTEOjk2-4",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImI1OTc0YjZjNWQ2ZjJmMWVkYjg0LmFwcC5zYWdlLmNvbSIsImNueUlkIjoiR2FyZGVyIFN1cHBsaWVzIiwiYXV0aHpDb2RlIjoiZWIxYTRlZTBiMjVjNjgyYjJkZmMzNzg5OTcxNzFmYmJhYmE2NDA4NyIsInVzZXJJZCI6InJvc2Uud2hpdGUifQ.SdOUDrZE80FUNq9hO0ZhgXPOttb4WhXRrVOGzRhbC1I",
"expires_in": 43200
}
Refresh token request
To request a refresh token, send a POST request to the following endpoint with the listed parameters:
https://api.intacct.com/ia/api/v1/oauth2/token
Parameter |
Value |
---|---|
grant_type |
refresh_token |
refresh_token |
The refresh token from the previous response |
client_id |
Your application's client ID |
client_secret |
Your application's client secret |
entity_id |
(optional) The ID of the entity that you want the user to have access to. Default is a top-level access token. |
Sample refresh token request:
curl --location --request POST 'https://api.intacct.com/api/v1/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImI1OTc0YjZjNWQ2ZjJmMWVkYjg0LmFwcC5zYWdlLmNvbSIsImNueUlkIjoiR2FyZGVyIFN1cHBsaWVzIiwiYXV0aHpDb2RlIjoiZWIxYTRlZTBiMjVjNjgyYjJkZmMzNzg5OTcxNzFmYmJhYmE2NDA4NyIsInVzZXJJZCI6ImRhaXN5LmJsdWUifQ.9uMW6BqnYNTbS3x7XYSSU1rq_jxi29F7FfWTEOjk2-4' \
--data-urlencode 'client_id=92d4dcf414e6a2c3d78d.app.sage.com' \
--data-urlencode 'client_secret=a55a58f1aeaf09116cbe1bf28025c183e778268c'
Sample response:
{
"token_type": "Bearer",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImI1OTc0YjZjNWQ2ZjJmMWVkYjg0LmFwcC5zYWdlLmNvbSIsImNueUlkIjoiR2FyZGVyIFN1cHBsaWVzIiwiYXV0aHpDb2RlIjoiZWIxYTRlZTBiMjVjNjgyYjJkZmMzNzg5OTcxNzFmYmJhYmE2NDA4NyIsInVzZXJJZCI6ImRhaXN5LmJsdWUifQ.9uMW6BqnYNTbS3x7XYSSU1rq_jxi29F7FfWTEOjk2-4",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImI1OTc0YjZjNWQ2ZjJmMWVkYjg0LmFwcC5zYWdlLmNvbSIsImNueUlkIjoiR2FyZGVyIFN1cHBsaWVzIiwiYXV0aHpDb2RlIjoiZWIxYTRlZTBiMjVjNjgyYjJkZmMzNzg5OTcxNzFmYmJhYmE2NDA4NyIsInVzZXJJZCI6InJvc2Uud2hpdGUifQ.SdOUDrZE80FUNq9hO0ZhgXPOttb4WhXRrVOGzRhbC1I",
"expires_in": 43200
}
Authorization code grant type with PKCE flow
The proof key for code exchange (PKCE) grant type is an extension of the OAuth 2.0 authorization code grant type. It adds an additional layer of security by requiring the client to generate a cryptographically random secret called the code verifier that is used to generate a code challenge sent to the authorization server. This prevents authorization code interception attacks. PKCE is recommended for mobile apps and public clients where storing the client secret is unsafe.
Follow these steps to get an access token using the PKCE flow:
-
Generate a cryptographically random code verifier (43-128 characters):
uuidgen | tr -d '-' | cut -c1-32 | base64 code_verifier = "zWiRBuiUcmnIbPBCoNqA5cWDFuaEZwZ7jLJJGJ4P3NQ"
-
Generate the code challenge by running the code verifier through a one-way hash function. This is typically done by taking the SHA256 hash of the code verifier and then URL-encoding the result:
echo -n zWiRBuiUcmnIbPBCoNqA5cWDFuaEZwZ7jLJJGJ4P3NQ | openssl dgst -sha256 -binary | base64 | tr '+/' '-_' | tr -d '=' code_challenge = "manPXpjp75EFeofO+YWtY3gIPp0S6/CJ+ciRJyYIonw"
-
Create an authorization request by redirecting the user to the authorization server’s authorize endpoint.
https://api.intacct.com/ia/api/v1/oauth2/authorize
Include the following parameters:
-
response_type
-code
-
client_id
- Your application's client ID -
state
- A random value to use to validate the response -
redirect_uri
- The redirect URI set for your application in the Sage App Registry -
code_challenge
- The code challenge generated in the prior step -
code_challenge_method
-S256
Sample PKCE authorization request:
https://api.intacct.com/ia/api/v1/oauth2/authorize?response_type=code&client_id=d4f2b6b318174b9a60a7.INTACCT.app.sage.com&state=0d091469-c244-4056-a23d-49e6a6cc93d7&redirect_uri=https://mysite.com/callback&code_challenge=manPXpjp75EFeofO-YWtY3gIPp0S6_CJ-ciRJyYIonw&code_challenge_method=S256
-
-
Use your credentials to log in and grant the requested permissions to receive the authorization code:
{ "code": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImQ0ZjJiNmIzMTgxNzRiOWE2MGE3LklOVEFDQ1QuYXBwLnNhZ2UuY29tIiwiY255SWQiOiJvYXV0aDJpaSIsImF1dGh6Q29kZSI6IjliMWQ1ZjhkNjNmMGY4NmU3YzU5YjE1MmRkMzg4OWQ5ODJkOTM4NWQiLCJ1c2VySWQiOiJBZG1pbiJ9.EE3jzQQ4--0JM2z7eO3DEBDFD6Nn4S5swyrtkW4Lt9o", "state": "0d091469-c244-4056-a23d-49e6a6cc93d7" }
-
Exchange the authorization code for an access token by sending a POST request to the token endpoint. This request must include the code verifier:
curl --location 'https://api.intacct.com/ia/api/v1/oauth2/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --header 'Cookie: DFT_LOCALE=en_US.UTF-8' \ --data-urlencode 'grant_type=authorization_code' \ --data-urlencode 'code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImQ0ZjJiNmIzMTgxNzRiOWE2MGE3LklOVEFDQ1QuYXBwLnNhZ2UuY29tIiwiY255SWQiOiJvYXV0aDJpaSIsImF1dGh6Q29kZSI6IjliMWQ1ZjhkNjNmMGY4NmU3YzU5YjE1MmRkMzg4OWQ5ODJkOTM4NWQiLCJ1c2VySWQiOiJBZG1pbiJ9.EE3jzQQ4--0JM2z7eO3DEBDFD6Nn4S5swyrtkW4Lt9o' \ --data-urlencode 'redirect_uri=https://mysite.com/callback' \ --data-urlencode 'code_verifier=zWiRBuiUcmnIbPBCoNqA5cWDFuaEZwZ7jLJJGJ4P3NQ' \ --data-urlencode 'client_id=*******' | jq
-
The authorization server verifies the code challenge matches the code verifier and issues an access token:
{ "token_type": "Bearer", "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImI1OTc0YjZjNWQ2ZjJmMWVkYjg0LmFwcC5zYWdlLmNvbSIsImNueUlkIjoiR2FyZGVyIFN1cHBsaWVzIiwiYXV0aHpDb2RlIjoiZWIxYTRlZTBiMjVjNjgyYjJkZmMzNzg5OTcxNzFmYmJhYmE2NDA4NyIsInVzZXJJZCI6InJvc2Uud2hpdGUifQ.SdOUDrZE80FUNq9hO0ZhgXPOttb4WhXRrVOGzRhbC1I", "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImI1OTc0YjZjNWQ2ZjJmMWVkYjg0LmFwcC5zYWdlLmNvbSIsImNueUlkIjoiR2FyZGVyIFN1cHBsaWVzIiwiYXV0aHpDb2RlIjoiZWIxYTRlZTBiMjVjNjgyYjJkZmMzNzg5OTcxNzFmYmJhYmE2NDA4NyIsInVzZXJJZCI6ImRhaXN5LmJsdWUifQ.9uMW6BqnYNTbS3x7XYSSU1rq_jxi29F7FfWTEOjk2-4", "expires_in": 28800 }
Client credentials grant type
The client credentials grant type is supported for applications needing direct access without user interaction.
To use the client credentials grant type, the client application must be associated with a Web Services user and explicitly authorized in your company's configuration:
-
Create a Web Services user:
- If the company already has a Web Services user defined for your application, you can skip this step.
- Have an admin user log in to the company and navigate to Company > Admin > Web Services Users > Add .
- Create a new Web Services user and assign the necessary permissions or role.
-
Authorize the client application:
- Navigate to Company > Setup > Company > [Edit] > Security > Authorized Client Applications > Add .
- Enter the Client ID for your application.
- Enter the Web Services User ID created in step 1. This field is case-sensitive, so ensure you enter it exactly as it was created.
After these steps are completed, your client application is authorized to request client credentials tokens.
To request client credentials tokens, send a POST request to the following endpoint with the listed parameters, including either username
or session_id
:
https://api.intacct.com/ia/api/v1/oauth2/token
Parameter |
Value |
---|---|
grant_type |
client_credentials |
client_id |
Your application's client ID |
client_secret |
Your application's client secret |
username |
(optional) User ID to log in as, in userId@companyId|entityId format. Required if not using session_id . |
session_id |
(optional) Valid UI or API session ID. Required if not using username . |
Sample client credentials request with username
:
curl -s --request POST 'https://api.intacct.com/ia/api/v1/oauth2/token' \
--header 'Content-Type: application/json' \
--data-raw '{
"grant_type": "client_credentials",
"client_id": "*********",
"client_secret": "*********",
"username": "Admin@oauth2_main2|Central Region" }'
Sample client credentials request with session_id
:
curl -s --request POST 'https://api.intacct.com/ia/api/v1/oauth2/token' \
--header 'Content-Type: application/json' \
--data-raw '{
"grant_type": "client_credentials",
"client_id": "*********",
"client_secret": "*********",
"session_id": "CkAU0b-G_RCd42yvvJvCo7aUEJwmVwcCFNG-xJE6neNsr7ybwuKriRKe" }'
Sample response:
{
"token_type": "Bearer",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImI1OTc0YjZjNWQ2ZjJmMWVkYjg0LmFwcC5zYWdlLmNvbSIsImNueUlkIjoiR2FyZGVyIFN1cHBsaWVzIiwiYXV0aHpDb2RlIjoiZWIxYTRlZTBiMjVjNjgyYjJkZmMzNzg5OTcxNzFmYmJhYmE2NDA4NyIsInVzZXJJZCI6ImRhaXN5LmJsdWUifQ.9uMW6BqnYNTbS3x7XYSSU1rq_jxi29F7FfWTEOjk2-4",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImI1OTc0YjZjNWQ2ZjJmMWVkYjg0LmFwcC5zYWdlLmNvbSIsImNueUlkIjoiR2FyZGVyIFN1cHBsaWVzIiwiYXV0aHpDb2RlIjoiZWIxYTRlZTBiMjVjNjgyYjJkZmMzNzg5OTcxNzFmYmJhYmE2NDA4NyIsInVzZXJJZCI6InJvc2Uud2hpdGUifQ.SdOUDrZE80FUNq9hO0ZhgXPOttb4WhXRrVOGzRhbC1I",
"expires_in": 43200
}
Revoke a token
You may want to revoke an active token when it is no longer needed or if a security concern arises:
- If you suspect a token has been compromised, revoking it immediately limits potential risk.
- To ensure inactive or idle sessions are closed as part of a security best practice.
- If a user's role is downgraded or permissions are reduced, revoking the current token ensures the user can no longer access data beyond their updated permissions.
To revoke an access or a refresh token, send a POST request to the following endpoint with the listed parameters:
https://api.intacct.com/ia/api/v1/oauth2/revoke
Parameter |
Value |
---|---|
token |
Access token or refresh token |
Sample revoke token request:
curl --location --request POST 'https://api.intacct.com/ia/api/v1/oauth2/revoke' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRJZCI6ImI1OTc0YjZjNWQ2ZjJmMWVkYjg0LmFwcC5zYWdlLmNvbSIsImNueUlkIjoiR2FyZGVyIFN1cHBsaWVzIiwiYXV0aHpDb2RlIjoiZWIxYTRlZTBiMjVjNjgyYjJkZmMzNzg5OTcxNzFmYmJhYmE2NDA4NyIsInVzZXJJZCI6ImRhaXN5LmJsdWUifQ.9uMW6BqnYNTbS3x7XYSSU1rq_jxi29F7FfWTEOjk2-4'
Sample revoke token response:
{
"revoked": true
}
Entity-level access
Multi-entity companies have a top-level parent entity with one or more sub-entities underneath. These sub-entities may own their records, and the REST API provides mechanisms to interact with them. You must first obtain a top-level access token as described in Authorization code grant type or Client credentials grant type.
Send a single request to a sub-entity
To access records owned by a sub-entity within a multi-entity company structure, use the X-IA-API-Param-Entity
header to specify the entity ID (company-config/entity.id
property), for example Central Region
:
# Get Vendor List with 'X-IA-API-Param-Entity' Header
curl --request GET 'https://api.intacct.com/ia/api/v1/objects/vendor' \
--header 'Content-Type: application/json' \
--header 'X-IA-API-Param-Entity: Central Region' \
--header 'Authorization: Bearer <top_level_access_token>'
Change to a sub-entity access token
You can also switch from a top-level access token to a sub-entity access token. This allows you to utilize the new access token in subsequent REST API calls for creating and retrieving sub-entity records. To obtain a sub-entity token, set the location_id
parameter to the sub-entity ID (company-config/entity.id
property) for your sub-entity in the Refresh token request:
# Refresh Token to Get Sub-Entity Access Token
curl -k --request POST 'https://api.intacct.com/ia/api/v1/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'client_id=*********' \
--data-urlencode 'client_secret=*********' \
--data-urlencode 'refresh_token=<refresh_token>' \
--data-urlencode 'location_id=Central Region'
You can now use the new token to access records specific to the sub-entity.
Test your OAuth 2.0 integration
This section provides the steps and PHP code samples for testing your integration in a development environment. This can be done either locally, using a self-signed SSL certificate and a custom domain mapped to localhost
, or with a production domain.
Prerequisites
For local testing:
- Self-signed SSL certificate - Required for HTTPS communication.
-
Hosts file update - Map a custom domain (e.g.,
mycustomdomain.com
) tolocalhost
. - Sage app registry - Add the custom domain to your application's callback URI list. See the Get API keys topic for more details.
For testing with a production domain:
- Valid SSL certificate - Ensure your domain has a valid SSL certificate.
- Domain configuration - Set up the domain and ensure it points to your server.
- Sage app registry - Add the production domain to your application's callback URI list.
Test your integration
You can download and extract the OAuth 2.0 example zip file that contains these code samples:
-
auth_flow_sample.php
-
callback.php
-
exchange_token.php
Replace mycustomdomain
with your domain name. Provide the client ID and client secret values where needed. Make sure to store your credentials securely and exclude files that contain them from your remote repository.
-
Implement the OAuth 2.0 authorization flow.
This script generates an authorization URL and provides a link for obtaining an access token (
auth_flow_sample.php
).<?php define("CALLBACK_URL", "https://mycustomdomain.com/callback.php"); define("AUTH_URL", "https://api.intacct.com/ia/api/v1/oauth2/authorize"); define("CLIENT_ID", "***********"); define("SCOPE", "offline_access"); // Optional, used to return the refresh token with the access token. $url = AUTH_URL . "?" . "state=active" . "&response_type=code" . "&client_id=" . CLIENT_ID . "&scope=" . SCOPE . "&redirect_uri=" . CALLBACK_URL; ?> <a href="<?php echo $url; ?>">Get Access Token</a>
-
Handle the OAuth 2.0 callback and token exchange.
This script handles the OAuth 2.0 callback and exchanges the authorization code for an access token (
callback.php
).<?php $code = $_GET['code']; $postArray = array( 'grant_type' => 'authorization_code', 'client_id' => '******', 'client_secret' => '*******', 'code' => $code, 'redirect_uri' => 'https://mycustomdomain.com/callback.php' ); $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.intacct.com/ia/api/v1/oauth2/token", CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, // Ignore SSL certificate validation CURLOPT_POSTFIELDS => http_build_query($postArray), CURLOPT_HTTPHEADER => array("Content-Type: application/x-www-form-urlencoded") )); $response = curl_exec($curl); $decoded = json_decode($response, true); $access_token = $decoded['access_token']; $refresh_token = $decoded['refresh_token']; curl_close($curl); echo "Access Token: " . $access_token . "<BR><BR>"; ?> Exchage Refresh token for new access token <a href="exchange_token.php?refresh_token=<?php echo $refresh_token; ?>">here</a>.
-
Exchange the refresh token for a new access token.
This script exchanges a refresh token for a new access token. Optionally, you can include an
entity_id
parameter to retrieve an entity-level access token (exchange_token.php
).<?php $refresh_token = $_GET['refresh_token']; $postArray = array( 'grant_type' => 'refresh_token', 'client_id' => '********', 'client_secret' => '********', 'refresh_token' => $refresh_token, 'entity_id' => '10' // Optional, specify entity_id for entity-level access token. Obtain a top-level access token if entity_id is omitted. ); $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://api.intacct.com/ia/api/v1/oauth2/token", CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, // Ignore SSL certificate validation CURLOPT_POSTFIELDS => http_build_query($postArray), CURLOPT_HTTPHEADER => array("Content-Type: application/x-www-form-urlencoded") )); $response = curl_exec($curl); $decoded = json_decode($response, true); $access_token = $decoded['access_token']; curl_close($curl); echo "New Access Token: " . $access_token; ?>
Tutorials
See the PHP tutorial or the Node.js tutorial for more details on how to authenticate with the OAuth2 server, and send requests to the REST API.