API Reference

The SmoothIntegration API is organized around a minimal REST API and WebSockets. Our API only accepts and responds with JSON-encoded objects.

SmoothIntegration works on pull-based events. You dictate when and how fast you would like to consume these Events. Events are consumed through a WebSocket connection. We highly recommend using our SDK to consume events. Currently this is only available on Node.js, but we are working on adding support for other languages.

Quick Start

Minimal example to start pulling live data from SmoothIntegration using the NodeJS SDK.
Requires: A SmoothIntegration Organisation and API Key.

Read Getting Started for a more in-depth guide on how to fully implement SmoothIntegration.

Authentication

SmoothIntegration uses API Keys to authenticate requests. When using the,
- REST API the api key should be provided with every request in the header x-api-key .
- SDK the api key should be provided when creating a new instance of the SDK.
- Custom WebSocket Implementation the api key should be provided when emitting the init event.

You will receive your API Key when you onboard with SmoothIntegration. Don't have an account yet? Reach out to [email protected]

Getting Started

Running a production grade integration with SmoothIntegration is a simple process. Commonly it consists of 2 services, a small REST API , and a Worker to ingest the events from SmoothIntegration.

The Worker will be used to consume any events from SmoothIntegration. You can store the incoming data in whatever data store you require for your business, Postgres, ElasticSearch, or for this demo, simply in memory.

The REST API will be used to proxy requests to the SmoothIntegration, this is required as requests to the SmoothIntegration API must be authenticated with your API Key, which you do not want to expose to your clients.

For the sake of this demo, we will be combining these into a single server. This is completely fine to do for smaller integrations, but we recommend separating them as you grow, as the worker(s) will likely require many more resources than the REST API.

First we will need a tenant ID, this is a unique identifier for your customer. For this demo we will be creating a Tenant by hand through the REST API.

Now that we have a tenant we can start with creating a new node project and installing express as our REST API server, and the SmoothIntegration SDK to make our lives easier.

Now we can create our index.js file, and start setting up our server. for this demo we will be allowing our users to connect to their Xero account, and we will store the data in memory, allowing the users to see a count of their invoices.
First we use the SDK to allow users to start the authentication process for Xero.

Next, to make sure we can use Xero as a data source for your organisation, follow the steps in the Xero Integration section. Feel free to use any of the other integrations we support, but if you do, make sure to retrieve the appropriate consent url.

And that is all there is to it! We can now try it out by running

and navigating to http://localhost:8080/connect-xero
You will be redirected to the Xero consent page, and once you have connected, SmoothIntegration will already be importing your data! So next up, let's start ingesting this data, add the following code to the existing index.js

Let's quickly add a simple HTTP endpoint to get a count to wrap up our demo product.

Now restart the server, and you will see the invoice events flowing in! Navigate to http://localhost:8080/count to see the count of invoices in the connected Xero Organisation.

Congratulations, you now have a great integration with Xero! Next, we recommend you do the following,
    - Store the data in an actual database.
    - Make sure your api key is stored securely, like in an environment variable.
    - Learn more about the Events SmoothIntegration produces.
    - Create and store the Tenant IDs, so you can have more than one customer.

SDK
Structure

SmoothIntegration is structured as your one Organisation which has many Tenants and each tenant has many DataSources

Organisation You will have exactly one organisation, this represents your business, not your customers. Your organisation holds data specific to you, like your Xero Oauth credentials, integration configuration details, and your API Key

Tenant Represents one of your customers. Whenever you onboard a new customer, you will need to create a new tenant through the REST API. A single tenant can hold many DataSources

DataSource A singular external data source, IE a Xero Organisation, or a Quickbooks Account. DataSources are unique to a tenant, if a Xero Organisation is connected to multiple tenants, then these will be separate entities

Events

Events are the core of SmoothIntegration. Events are emitted by SmoothIntegration as we import data from your DataSources. Events are consumed through a WebSocket connection. We recommend using our SDK to consume events.

Events in SmoothIntegration are consumed on a pull basis. This means that you dictate when and how fast you would like to consume these events.

Event Structure
Field Description
type one of active or deleted. Active means the document was created, updated, or restored. Deleted means the document was either hard deleted, soft deleted, archived, voided, etc.
event_id string containing a decimal representation of a 64-bit integer, will never contain decimals, monotonic value meaning a higher value happened later in time.
tenant_id lowercase uuid with dashes. Represents the tenant to which this data belongs in your organisation.
data_source_id lowercase uuid with dashes. Represents the data source of the tenant to which this data belongs in your organisation.
document_id lowercase uuid with dashes. Globally unique identifier specific to this document, for this data source, for this tenant, for your organisation. Please note that this is not the identifier of this document in the external system.
document_type identifier detailing for which data type this event is. For instance, xero.account, xero.balances or quickbooks.invoice. Please reference the integration specific documentation for the comprehensive list of document types for your integrations.
document The data as retrieved from the external system. Exact content depends on the document_type and the structure defined when the pull was initiated.
Event Idempotency

SmoothIntegration guarantees that events will be delivered at least once. We do not guarantee events will not be delivered more than once. This means that you should be prepared to handle duplicate events. There are several approaches to handling duplicate events,

The most common solution is to implement your event handlers in an idempotent manner, meaning that the same event can be processed multiple times, keeping the same output. For instance, when handling a "document created" event, the logic would be like,

Make sure the handler is otherwise pure, meaning it does not have any side effects.

Event Types

SmoothIntegration produces 3 types of events for you to consume, indicated by the document_type property. These are active , archived and deleted .

active events are created whenever a document is created, updated, or restored from being archived. These events contain the full document data in the document key. For active events, the document will contain the full document.

archived events are created whenever a document is soft deleted. These events still contain the full document data in the document key. Actions like voiding an invoice, or marking an account as inactive are considered soft deletes. For these events, the document will still contain the full document.

deleted events are created whenever a document is hard deleted. For these events, the document will be an empty object {} . Hard deleted documents will never be restored.

deleted events will only be created if a prior active or archived event was created for the document. This means on your first import, you will not receive any archived documents. This is because some platforms like QuickBooks Online hard delete data after a month, meaning we would never be able to give you a consistent view of the data, if we were to include archived data in the first import.

Event Ordering

SmoothIntegration does not guarantee that events will be delivered in order. This means that you should be prepared to handle events that are out of order. At some point you will encounter a situation where you receive a "document deleted" event after the "document created" event. This is normal and expected.

SmoothIntegration does guarantee that event_id are globally unique, and monotonic, meaning a higher ID occurred after a lower ID.

A common solution to make sure you only use the latest version of any document, is to only update the document if the event_id is higher than the last event_id you processed for that document. So an event handler for any document event would be

Event Failure & Responses

In any system, errors occur causing you to fail to process an event. Database writes can fail, external services may be down, or one of many other reasons.

SmoothIntegration will requeue any failed event up to 5 times, before it dies. An event is considered "failed" if you send a "event_response" event with payload ["the_event_id", "failure"] . If you're using the SDK, this will be done whenever any error is thrown in your handler.

Likewise, if you event succeeds, it is important to send a "event_response" event with payload ["the_event_id", "success"] . Letting SmoothIntegration know you've properly handled the event.

To handle expected errors, like a database connection being lost, we recommend you simply pause the import of data for a bit. This is possible because SmoothIntegration operates on a pull basis, you can simply stop pulling events until the issue is resolved. It is important to note that SmoothIntegration does not provide any time based delay before retrying an event, which is why you should wait for your issue to be resolved before continuing.

Sometimes, unexpected errors occur, like a field you require is missing, causing an exception. In these cases, the event will be tried up to 5 times. It will then stop being sent, to make sure other events can continue processing. Once you have fixed the issue and deployed your fix, you can tell SmoothIntegration to retry all dead events, by calling the API,

Before retrying every event though, we recommend you first test with just a couple events. This can be achieved by passing an optional path parameter at the end indicating how many to retry.

Normalisation

Smooth Integration provides 3 format levels in which you can retrieve data, raw , normalised , and domain .

With raw , you will get the documents as is from the data source, not modified in any way.

With normalised , we will do various transformations to create consistency both between the integration itself, but also all different integrations. These transformations are

Data Format Example
Timestamp ISO 8601 UTC datetime strings with millisecond precision2023-05-22T16:44:21.000Z
Date ISO 8601 date string2023-05-22
Monetary String with dot as decimal separator without any redundant decimals12345.67
Currency Code ISO 4217 Code in capital lettersUSD
UUID lowercase string with dashes01234567-89ab-cdef-0123-456789abcdef
Percentage numerical value where 1.0 represent 1%12.5

On top of that, we transform all keys into snake_case to ensure a consistent and non-ambiguous naming convention between all integrations.

We recommend you use the normalised format, as it will handle many edge cases you may not expect, like Xero's epoch datetime strings containing negative epochs, or precision errors in numerical values.

Integrations

SmoothIntegration supports a wide array of integrations. We are constantly adding new integrations, if you have a specific integration you would like to see, please reach out to us at [email protected]

Balances
Chart of Accounts
Invoices
Bills
Invoice Credit Notes
Bill Credit Notes
Customers
Suppliers
Bank Accounts
Company Info
Items
Purchase Orders
Sales Orders
Tax rates
Tracking categories
Budgets
Budget Balances
Refresh Interval (minutes)
Burst Refresh Interval (minutes)
QuickBooks Online
30 1
Xero
60 N/A
MYOB
30 N/A
FreeAgent
360 N/A
Data Refresh Interval

SmoothIntegration will optimize the available requests per integration based on the rate limits set by the integration. For most use cases this will provide the required semi-realtime experience your customers expect.

In some scenario's though, your customer may want to indicate when they need updated data, as they just made a change in the external system themselves. To allow for this, you can use the following endpoint up to 20 times per day, per data source. This will trigger an immediate refresh of the data.

Data Burst Refresh

In some scenarios, you know when one of your customers is actively making use of your product. When you know this, you can make use of the Data Burst Refresh feature. This allows you to increase the refresh rate temporarily for a specific tenant, so that they can have a more real-time experience whilst using your product. Due to the increase in required network requests, this feature can only be used up to 3 hours, every 24 hours. You can enable this by calling the API, specifying the tenant to burst and the duration in minutes.

Integration Customisation

Out of the box, we provide great success, error, and warning pages for the authentication flows for every integration. We understand that you may want to customise these page to provide additional information, or change the UX to fit your brand better.

For every integration you can set the success_url , failure_url and no_new_tenants_url .

If you configure a custom no_new_tenants_url , we will redirect the user to this address when a user tries to connect a data source to SmoothIntegration, but the tenant is already connected. This commonly happens when a user accidentally selects the wrong organisation to connect.

If you configure a custom success_url , we will redirect the user to this address when they successfully connect their data source to SmoothIntegration. We additionally will include the name of the organisation the user connected as a query parameter for you to use to improve the user experience.

If you configure a custom failure_url , then we will redirect the user to this address when they fail to connect their data source to SmoothIntegration for any reason.

Xero

How to set up Xero for your SmoothIntegration.

1. First you will need to register your Xero Developer account, you can do this at developer.xero.com

2. Log into your Xero Developer account, and navigate to My Apps

3. Click on the New App button, fill in the required details and create the Xero App,
    - App name enter the name of your product, not "SmoothIntegration"
    - Integration type select Web app, Standard auth code
    - Company or application URL enter the url of your product, not "SmoothIntegration"
    - Redirect URI to https://api.smooth-integration.com/xero/callback

4. Once you have created the app, you will be taken to the app details page. Navigate to the Configuration section. Once here, press Generate another secret , and save the Client id & Client secret for the next step.

5. Navigate to the SmoothIntegration Dashboard and press Enable Xero and enter the Client id & Client secret from the previous step.

Your Xero App is now connected to SmoothIntegration. And you're ready to start accessing your customers Xero data! Simply get a connection url for your users from the SDK by getting a consentUrl for appropriate tenantId.

QuickBooks

How to set up QuickBooks Online for your SmoothIntegration.

1. First you will need to register your Intuit Developer account, you can do this at developer.intuit.com

2. Log into your Intuit Developer account, and navigate to Apps Dashboard

3. Click on the + button, fill in the required details and create the QuickBooks App,
    - App name enter the name of your product, not "SmoothIntegration"
    - Add permissions select com.intuit.quickbooks.accounting

4. Once you have created the app, you will be shown your credentials, and save the Client id & Client secret for a later step.

5. Navigate to Settings -> Redirect URIs . Add the following URI https://api.smooth-integration.com/quickbooks/callback .

6. Navigate to the SmoothIntegration Dashboard and press Enable QuickBooks and enter the Client id & Client secret from the previous step.

Your QuickBooks App is now connected to SmoothIntegration. And you're ready to start accessing your customers QuickBooks data! Simply get a connection url for your users from the SDK by getting a consentUrl for appropriate tenantId.

MYOB

How to set up MYOB for your SmoothIntegration.

1. First you will need to request a MYOB Developer account, you can do this at developer.myob.com/become-a-myob-developer-partner/

2. Once your account is approved, log into your MYOB Developer account, and navigate to the Developer Dashboard

3. Click on the Register App button, fill in the required details and create the MYOB App,
    - App Name enter the name of your product, not "SmoothIntegration"
    - Redirect Uri enter https://api.smooth-integration.com/myob/callback
    - Web Site Address enter the home page of your product if you have one.
    - Description enter the description of your product, not "SmoothIntegration"

4. Navigate to the SmoothIntegration Dashboard and press Enable MYOB and enter the Api Key which you can find in the Developer Dashboard.

Your MYOB App is now connected to SmoothIntegration. And you're ready to start accessing your customers MYOB data! Simply get a connection url for your users from the SDK by getting a consentUrl for appropriate tenantId.

FreeAgent

How to set up FreeAgent for your SmoothIntegration.

1. First you will need to register your FreeAgent Developer account, you can do this at dev.freeagent.com/

2. Log into your FreeAgent Developer account, and navigate to My Apps

3. Click on the Create New App button, fill in the required details and create the FreeAgent App,
    - Name enter the name of your product, not "SmoothIntegration"
    - Description enter the description of your product, not "SmoothIntegration"
    - App Homepage URL enter the home page of your product
    - OAuth Redirect URIs include https://api.smooth-integration.com/freeagent/callback
    - Enable Accountancy Practice API should be true

4. Navigate to the SmoothIntegration Dashboard and press Enable FreeAgent and enter the OAuth identifier & Secret from the previous step.

Your FreeAgent App is now connected to SmoothIntegration. And you're ready to start accessing your customers FreeAgent data! Simply get a connection url for your users from the SDK by getting a consentUrl for appropriate tenantId. For FreeAgent, a secondary parameter sandbox can be passed. This should be true if you're trying to connect a sandbox organisation for testing purposes. Ensure this is false when working with real users.

Making Requests

Retrieving data is commonly not the only thing you would like to do when integrating with a third party. You may want to create or delete records, or get data not exposed by our API like a report. For this purpose, we have a proxy endpoint that will allow you to make requests to the external system. This proxy will handle everything like authentication, rate limiting, and where necessary, request idempotency. So there is no need to add authentication headers like Authorization & Xero-Tenant-Id to your requests. Headers like Content-Type will be set as well, but you can override them if you wish.

Be aware that this shares the same rate limits as the rest of the API. So excessive use will result in rate limiting, and data imports to stop until the rate limit is reset.

The proxy will forward only known headers to the 3rd party API, these are,
- Accept
- Content-Type
- If-Modified-Since
- includeArchived
- Idempotency-Key
We're always on the look out for more headers used by the APIs. If one is missing, please let us know at [email protected], and we'll include it as soon as possible.

SmoothIntegration will return the response as is. Requests will not be retried.

Features

On top of the incredibly simple integrations, Smooth Integration also provides some Quality of Life features out of the box, which normally would require joining different entities together
- Deep Links
- Currency Codes & Formatting

Currencies

Whenever you work with monetary values in APIs, you will soon encounter that it is not always obvious what currency a monetary value is in. We remove this ambiguity for you by inserting two new keys into the document for every monetary value.
one key is the attribute plus _code which will contain the three letter ISO code like USD .
the second attribute is the attribute plus _formatted , which will contain the monetary value properly formatted, ready to display to end users.
This only happens whenever you use the normalised or domain document formats.

Note: for ambiguous currency symbols, the extended symbol will be used. Since there are many dollar currencies, we will use the extended symbol like USD instead of the ambiguous $

Migrating to SmoothIntegration

TODO