Integrating with an ERP
Introduction
While the Invoice Portal provides an excellent standalone solution, most companies already have an existing workflow to create invoices in their backoffice systems (such as an ERP). Although the particular system you are integrating may be classified as something other than "ERP", we will refer to all such backoffice systems as ERPs in this document. In order to faciliate using the Invoice Portal with these existing workflows, we provide an extensive Public API. This API works well in an ETL setting and provides everything you need to sync invoice-related entities.
Caveats
There are some caveats to understand before getting started.
First, note that the Invoice Portal does not provide a complete eCommerce solution. Instead, the Invoice Portal extends existing eCommerce solutions to add invoicing. Because of this, you will need to ensure that you can integrate the entities the Invoice Portal depends on with the ERP. In general, this is feasible because any such system will itself expose an API to access and manage those entities (after all, the Invoice Portal itself accesses these entities through such an API). You will need to determine whether you can write connectors for all the systems your particular use case involves before proceeding.
Second, note that the overall system will not be fully-consistent because the Invoice Portal manages its own data. Because you will only be synchronizing using ETL, it will be possible for the overall system to enter states that are considered invalid. For example, it is possible that a customer makes a payment on an invoice online, then makes another payment offline, and that these 2 payment amounts sum to more than the open invoice balance. With only online payments, the Invoice Portal can prevent such a situation from happening in the first place. With only offline payments, the ERP can also prevent such a situation from ever arising. But when both run independently, they can create conflicts in the overall system state because neither knows the entire system state at any time. There are ways to resolve these situations, but they will always depend on the specific use case. You will need to be able to determine when these situations can occur and communicate with your customer to determine the optimal solution. Note that these situations are rare, so most customers will know of a way to handle them that works for their business. We are happy to provide support in determining which features to leverage to provide these solutions. Please email support to request help from one of our Solution Architects should you need it.
API Access
You will need to provide the API token in each API call using the X-Auth-Token
header. The API token contains all the information we need to know which store we are managing data for. You can generate an API token for a store by clicking the API Tokens
link in its control panel navigation sidebar.
When creating the API token you will use, make sure to give it permissions for each endpoint you will need to use.
Concurrency Control
All of the REST-oriented endpoints support optimistic concurrency control using a "version" field. You simply pass back the "version" you read and the API will ensure that no other updates have been made to that resource since you read it. If no other updates were made, your update will be committed. Otherwise, your update will be rejected with a 409 Conflict
response. Use of the versioning mechanism is optional, meaning that you can accidentally overwrite another API consumer's changes if you do not use it. The optimistic concurrency control mechanism does not add any overhead, so you should always use it. When your updates are rejected with a 409 Conflict
response, you should re-read the entity and re-perform any computations you performed to recreate your update (do not increment the version number until "it works" as this means you are not taking into account the update that caused the conflict).
The operation-oriented endpoints rely on internal state machines and internal locking to determine whether to allow the operation to proceed. These endpoints acquire exclusive locks, then evaluate whether the operation is allowed in the current state. This prevents these operations from placing the underlying resource into an inconsistent state. You do not need to worry about corrupting state when using these endpoints because the API will reject any invalid operations.
Customers
The first entity to integrate will be customers. You will integrate customers using the underlying eCommerce platform. Below we link out to the API references for the platforms we support and provide an entity name level mapping for the customer related entities.
Platform Entity | ERP Entity | Invoice Portal Entity |
---|---|---|
Customer Group | Customer | Customer |
Customer | Contact | Payer |
Platform Entity | ERP Entity | Invoice Portal Entity |
---|---|---|
Company | Customer | Customer |
User | Contact | Payer |
Invoices
Once you have integrated Customers, you can integrate Invoices. Every Invoice must be associated with a Customer in the eCommerce platform. This means you must provision a Customer in the eCommerce platform before you can create an Invoice for that customer. Once the Invoice is created, any "Payer" for that Customer can make a Payment on the Invoice from the eCommerce website.
There are a few things you will find useful:
- Use the
externalId
andexternalCustomerId
fields to store information to help you look up Invoices later - Use the
advancedsearch
query interface for searching invoices.
Endpoints to Use:
I want to | Endpoint |
---|---|
Create an invoice | Create Invoice |
Update an invoice |
Payments
Every payment made by a "Payer" on the Invoice Portal is represented by a Payment resource. Due to the behavior driving nature of payments, you can only update certain fields on an online Payment resource. In addition, you are not able to create new online Payment resources via the API. We provide special endpoints for creating and updating offline Payment resources that allow you more control over the data stored for these payments.
I want to | Endpoint |
---|---|
Search for new payments | |
Set the externalId of an online payment | |
Update the status of a payment (online or offline) | |
Add an offline payment | |
Update fields of an offline payment |
Note that when a payment is paid or refunded on the Invoice Portal, receipts are generated. Receipts record notable events that happened for a payment that should be made visible to customers on the storefront. Receipts are never generated automatically for an offline Payment that you create. You should create receipts for these payments as needed. See the next section for more information.
Receipts
Receipts record notable events that happened for a payment that should be made visible to customers on the storefront. The Invoice Portal automatically creates these whenever an online Payment is paid or refunded. You need to create these "paid" and "refunded" receipts for offline Payments yourself. In addition, depending on the customer requirements, you may need to create additional receipts for a payment to give customers a record that their payment processed successfully.
I want to | Endpoint |
---|---|
Create a new receipt |
Credit Limit and Account Balance
The Invoice Portal has an optional credit limit feature that allows setting a credit limit for a Customer and keeping track of the Customer's current account balance. The Invoice Portal does these things automatically:
- When an order is placed on the eCommerce platform, if that order has not been paid, the account balance is incremented
- When an order is placed on the eCommerce platform, if that order's total plus the current account balance is greater than the credit limit, the order is put on hold
- When an invoice is created, check if an order matching its
orderNumber
has previously been incorporated into the account balance. If so, do nothing. Otherwise, increment the account balance by the invoice open balance. - When an invoice is updated, subtract the new open balance from the old open balance. Add this difference to the account balance.
TODO: Add strategy for properly setting account balance
We recommend you do something like the following:
0. Set "done" to true
1. Sync (orders / invoices / payments) from ERP to Web
* Set done to "false" if there were any entities synced in this step
2. Read (orders / invoices / payments) from Web. Build set of customer ids.
3. Read the account balance for each customer id from (2) from the Invoice Portal
4. Sync (orders / invoices / payments) from Web to ERP (make sure to read them again)
* If you encounter an additional entity from the set in (2), set "done" to false.
5. Read the new account balance for each customer in the set from the ERP.
6. Attempt to update the account balance on the Invoice Portal.
* If any conflicts occur, go back to (2)
7.
This will make the Invoice Portal account balance equal to the ERP amount. It is also guaranteed to not overwrite any automatic updates made by the Invoice Portal, as any such update would be triggered by events that will be replayed in the ERP (step 3) before computing the balance. The one caveat is that the balance will include the balances of any new orders / invoices created in the ERP after step 1 started, but those orders / invoices will not be synced over. You can repeat steps 1 - 6 until no changes are made if this is an issue.