A client for the Exact Online REST API.
Quickstart
credentials = [
client_id: System.fetch_env!("EXACT_CLIENT_ID"),
client_secret: System.fetch_env!("EXACT_CLIENT_SECRET"),
redirect_uri: "https://example.com/oauth/callback",
region: :nl
]
# Send the user here, then exchange the code from the callback.
Exact.OAuth.authorize_url(credentials)
{:ok, token} = Exact.OAuth.exchange_code(code, credentials)
:ok = Exact.TokenStore.ETS.put(:default, token)
client =
Exact.new(
token_store: Exact.TokenStore.ETS,
credentials: credentials
)
# Every other endpoint needs a division.
{:ok, division} = Exact.System.Me.division(client)
client = Exact.Client.put_division(client, division)
{:ok, page} = Exact.CRM.Account.list(client, select: ["ID", "Name"], top: 10)
page.resultsThere is a runnable walkthrough in the Livebook notebook.
What this library does for you
- refreshes the access token before it expires and once more on a 401, and
persists the rotated refresh token through an
Exact.TokenStore - unwraps the OData
denvelope so you get maps and lists, and decodes/Date(...)/strings intoDateTime - follows the
__nextcursor, seeExact.Client.stream/3 - turns non-2xx responses into
Exact.Errorwith a:reasonyou can match on, and retries transient failures honoringRetry-After - reports the rate limit state Exact Online sends on every response, see
Exact.RateLimit
What it does not do
Exact Online exposes around 600 resources. This library ships modules for the
ones most integrations start with (Exact.System.Me,
Exact.System.Division, Exact.CRM.Account, Exact.CRM.Contact,
Exact.Sales.SalesInvoice, Exact.Financial.GLAccount) and covers the rest
two ways: call any path with Exact.Client, or generate a module with
Exact.Resource.
The XML API, the bulk and sync endpoints and webhook signature verification
are not wrapped. Bulk and sync endpoints are reachable as ordinary paths, for
example Exact.Client.stream(client, "bulk/CRM/Accounts").
Summary
Functions
Builds a client. Delegates to Exact.Client.new/1.
Functions
@spec new(keyword()) :: Exact.Client.t()
Builds a client. Delegates to Exact.Client.new/1.