Integrate your ERP system with Zuora Billing ERP Fulfillment pattern
Overview
This guide will help you quickly integrate your ERP system with Zuora Billing, allowing you to price, bill, collect payments, and determine revenue at scale for both digital and physical goods. By the end of this guide:
- You will have written code that invokes the correct Zuora Billing API calls at each step.
- You will have performed an initial integration test.
Prerequisites
Before getting started, ensure you have the following:
- API Access Credentials : For both your ERP and Zuora Billing in both production and test/dev environments. Zuora’s Developer Get Started tutorial explains how.
- Basic Understanding of REST APIs : Familiarity with JSON and API calls.
- Access to a Zuora Billing Sandbox : Every Zuora customer is issued at least one sandbox. If you need one for this project you can request one from Zuora.
- Product Catalog Configuration : This document assumes pricing is captured in Zuora Billing’s Product Catalog. This is optional but is assumed here for clarity. Order capture in Zuora Billing is also excluded for clarity.
-
Familiar with Zuora Orders, Order Line Items
(OLI),
their state model
,
Subscriptions
, and the
Zuora Business Object model
. All orders will be captured in Zuora Billing as an "order". Each Order object includes at least one of (1), (2), or both:
- Physical goods order items will be captured in Zuora Billing as Order Line Items. In addition to an Order, Zuora Billing has a Fulfillment object where an Order Line Item may have one or more fulfillments that are fundamentally "shipments".
- Digital or recurring billing products and services are captured as Order Actions where Order Actions can create or modify one or more subscriptions. A Subscription captures the details of any recurring billing for digital goods or services.
- Fulfillment settings : We assume that the Zuora Billing, Billing Settings, Fulfillment Settings panel has been used to correctly define and configure carriers, systems, and locations appropriate for your business.
- ERP knowledge : Familiarity with your ERP system’s fulfillment processes and inbound webhook processing capabilities. Many companies have implemented middleware to manage communication between systems, just substitute "your middleware" for "your ERP" throughout the rest of this document. The Zuora setup is the same.
Integration guide
Step 1: Understand The integration patterns
Two out of the following three integration patterns between Zuora and your ERP are required for success:
-
ERP Fulfillment
:
Zuora Billing handles all orders and financial transactions. Your ERP manages the fulfillment of physical goods. This document describes this integration in detail. - ERP item level integration : You choose to centralize all your AR in your ERP system even though Zuora's AR and collections abilities are superior to your ERP's capabilities. This pattern is detailed in a companion guide, Integrate your ERP with Zuora Billing item level pattern .
-
Summary GL Integration
:
Your ERP receives summary journal entries from Zuora for financial reporting in your General Ledger. This integration pattern is detailed in a companion document, Integrating your ERP with Zuora Billing Summary GL . Zuora also provides support for this Summary GL integration with prebuilt connectors for some of the major ERPs. Check our Integration Hub documentation to see if you can avoid having to develop this integration point yourself.
The ERP item level pattern and the ERP fulfillment pattern are complementary. You will implement one or the other, but not both.
The following diagram is a simplified schematic of both these integrations:
In this guide, we will describe how to implement the "ERP Fulfillment" integration, shown by the two black lines between Zuora Billing Order Line Items and your ERP modules.
How to build the right-hand blue lines, the integration from Zuora Billing to your General Ledger is covered in the companion document referenced above, Integrating your ERP system with Zuora Billing (Summary GL). Zuora also provides prebuilt connectors for this Summary GL type connection.
Step 2: Set up your integration environment
- Zuora Sandbox : Make sure you have a Zuora Billing sandbox for development and test alongside your ERP test environment.
- Test Data : Work with your teams to define exhaustive sample orders and transactions in your Zuora Billing sandbox.
Step 3: Finalize scope with your teams
The standard steps in this integration include:
- Configure automated notification of physical goods' order line items from Zuora to your ERP.
- Configure your ERP to accept these notifications and process fulfillment of that Order Line Item.
- When fulfillment is complete, often when shipping occurs or when service is delivered, call the Zuora Billing API to inform Zuora Billing it is time to bill for these physical goods or services.
Review those solution steps with your teams. Do not skip this review. Ensure that you have completed all the following actions before proceeding:
- Determine if all Order Line Items will be sent to your ERP or if only a subset need be sent and how that subset will be identified automatically.
- Determine the fields and values required for ERP fulfillment to happen. Determine the fields in Zuora Billing Order Line Item and related objects that will be the source of each of these.
- Ensure Zuora Billing Custom Logic is being utilized to ensure default values, field lengths, and content are compatible with your ERP.
- Map the Zuora Billing Order Line Item State model to your ERP fulfillment process.
- Determine any needed custom fields on the Zuora Billing Order, Order Line Item, Fulfillment, or Fulfillment Item objects.
- Define the integration error reporting process, and determine who will be responsible for responding to issues.
- Edit the billing document templates for invoices, credit memos, and debit memo to include ERP supplied fulfillment information, such as tracking numbers and shippers. This will reduce the potential questions from customers about billing documents that could lengthen collection time.
- Determine if there will be partial shipments, where an order line item results in multiple shipments.
- Determine if there is a need to inform Zuora Billing when non-billable items have been fulfilled by your ERP.
- Determine how returns will be handled and how Zuora Billing is notified.
- Determine reconciliation reporting between Zuora Billing and your ERP.
-
Create a test plan. Be sure to include the test scenarios that verify:
- Orders that have no OLIs (physical goods), only subscriptions (digital goods or services) are processed correctly.
- Orders that have both physical and digital goods and services are processed correctly.
- Orders that are only for physical goods, so have only Order Line Items, are processed correctly.
Step 4: Submit API calls for integration
A: Configure automated notification for Order Line Items
Zuora Platform features include an Events and Notifications feature for automatically sending callouts to your systems. In our terminology, "notification", either email or callout(webhook), are triggered by system events. An event might be a new order or a new invoice, there are dozens predefined but you can also define your own. These events and notifications are created using a wizard and in this step we will use this wizard to define a callout notification for new Order Line Items. A single event, such as a new Order Line Item can trigger multiple notifications.
If your ERP cannot accept external webhooks from a SaaS platform such as Zuora Billing, brief instructions on how to query for new Order Line Items are included at the end of this section.
To access the wizard for creating a notification/webhook:
- In the Zuora UI, expand the Extension Studio section and select Events & Notifications .
- On the Custom Events tab, verify that there are no existing Order Line Item events defined. Look for OrderLineItem as the object. If there is a custom event already created for Order Line Items, review to see if it’s suitable. Note that you can have multiple notifications, webhooks, for the same event. In this guide we assume a new event and notification are needed.
-
Create a custom event.
- Click the Create Custom Event button on the top right.
-
Give your new event a name such as
Physical Goods Order Line Item
, and select Order Line Item from the Base Object list. -
Specify a trigger condition and this is probably when the field,
Item State is equal to Booked
. Do not use the legacy value, 'Item State (Old)'. - Click Save . The custom event is then created.
-
Create a new notification definition. Click the
Notification
tab, and then click the
Add New Notification
button on the top right.
- Follow the wizard steps beginning with On An Event Occurrence . The wizard allows you to create a new event for Physical Goods Order Line Item (Custom Event) . Specify your server, the authentication needed for that server, and the required payload or query string for sending Order Line Item details to your ERP.
- Specify the Communication Profile . This is a property of the customer billing account and is used to create target groups of customers for specific notifications. You should ensure that the billing accounts that should be sending notifications to your ERP system are using a communication profile that matches the one specified for your new OLI notification.
- After reviewing the notification detail, click Done .
-
Test your new notification is working by creating an order with an order line item for an account that has the correct communication profile. In addition to whatever you view at the target server, you can see a history of callouts for each account by scrolling to the bottom of the account detail screen in the UI. If notifications do not appear to work, verify:
- The right communication profile is enabled on the billing account being used in your testing. This is listed at the bottom of the billing account detail screen.
- That the communication profile is not muted. If it is, it will be in red. If it’s active, it will have a green bell logo.
- Are the authentication details correct for the server you are targeting? Are you authenticating using production credentials when the target is a test server?
- If you are new to Events and Notifications, it can be helpful to create a callout notification to a webhook service such as RequestBin or Beeceptor. These services do not require authentication. If this still doesn’t work, contact Zuora Support. Do not send real customer data to any of these third party services.
If your ERP cannot accept external web hooks from a SaaS platform such as Zuora, you can set up a polling service to query Zuora Billing for new order line items since the last time Zuora Billing was polled. Assuming polling is frequent, meaning at least once a day, you should use the synchronous Object Query feature to query order line items using List order line items.
Keep a high watermark using updatedDate
. You can sort on updatedDate
, so pull the new high water mark for your next object query from the last retrieved order line item. Below is an example of an Object Query call, but you need to provide the bearer token and change the updatedDate
based on the results of the last query.
The fields listed in this example is minimal, and you will likely require many more, including custom fields. This query looks for order line items from all accounts that have an Item State of Booked
and that were updated after 2:30:46pm on March 13th 2025. Check this good tutorial on using Object Query for more examples.
curl --request GET \
--url 'https://rest.apisandbox.zuora.com/object-query/order-line-items?\
orderlineitem.fields[]=orderId,id,itemNumber,itemName,itemState,quantity,billingRule,updatedDate&\
filter[]=itemState.EQ:Booked&\
filter[]=updatedDate.GT:2025-03-13T14:30:46-07:00' \
-H "Authorization: Bearer $ztoken" \
-H "Content-Type: application/json"
Since any change to an Order Line Item will update updatedDate
, you may get the same order line items being returned multiple times. You must ensure that it does not result in multiple shipments for the same order line item.
You should always capture the order line item ID and store this in your ERP or integration. It can be used later to update the order line item state once the ERP fulfillment has occurred and it is time to invoice.
B: Process fulfillments of order line items
The details of the fulfillment process are ERP-dependent and outside the scope of this document. In general, we assume your ERP is going to accept and then ship the order line items with each shipment being captured as a "Fulfillment" in Zuora Billing. Zuora Billing supports none, one, or many fulfillments (shipments) for each Order Line Item. You should update your tenants with lists of your shippers and shipping locations so these can be easily referenced and included along with tracking numbers when you create fulfillments in Zuora Billing. To achieve this, navigate to Billing Settings > Fulfillment Settings and complete the configuration. This information can then be included on an invoice to ensure prompt payment.
When the Order Line Item is captured in Zuora Billing, the Billing Trigger Rule field drives billing behavior:
-
A value of
Without Fulfillment
can be used to:
- Generate an invoice item charge for the entire Order Line Item amount when you set the Order Line Item State to Send To Billing . If you don’t explicitly specify State , the default is Executing .
- Skip billing for an Order Line Item. Set the State to Complete so you can skip Send To Billing .
- A value of Trigger As Fulfillment Occurs will invoice for fulfilled items as they ship. A single Order Line Item of 10 widgets might result in three shipments - one for 2 widgets, one for 3 widgets, and one for 5 widgets. This setting will result in three invoice items being created, one for each shipment. These invoice items can be on different invoices, so you don’t have to wait to fulfill an entire order line item to obtain payment. Refer to the example in the next section.
We assume your integration will notify Zuora Billing upon shipment or another appropriate event, setting either the Order Line Item State or Fulfillment State as appropriate. How to do so is described in the next step.
C: Notify Zuora Billing to invoice
As discussed in Step B, your ERP will tell Zuora when it is time to invoice as something has shipped or, optionally, when something has shipped for which no invoicing is needed. In this section, we will show examples of the following use cases:
- Notify Zuora Billing to invoice for an order line item without recording any fulfillment information.
- Notify Zuora Billing that a non-billable order line item has been fulfilled.
- Notify Zuora Billing that all or part of a billable order line item has been fulfilled (shipped).
C1: Bill for entire Order Line Item without recording any fulfillment information
To do this set the Item State to SentToBilling
, this requires the existing Item State to be either Executing
or Booked
. Order Line Items with an Item State of Completed
or Canceled
cannot be invoiced.
Use Update an order line item:
curl -i -X PUT --url 'https://rest.apisandbox.zuora.com/v1/order-line-items/8ad083f095911c7b01959163d2510cf0' \
-H "Authorization: Bearer $ztoken" \
-H "Content-Type: application/json" \
-d '{ "billTargetDate":"2025-03-16", "itemState":"SentToBilling" }'
Replace the base URL, bearer token, and item object ID as appropriate. If the order line item's billing rule isn’t set to TriggerWithoutFulfillment
, this call will fail.
C2: Non-billable order line item is complete without billing
Set the Item State to Complete
:
curl -i -X PUT --url 'https://rest.apisandbox.zuora.com/v1/order-line-items/8ad09e5495a403d60195a61f017018e2' \
-H "Authorization: Bearer $ztoken" \
-H "Content-Type: application/json" \
-d '{ "itemState": "Complete" }'
Again, the order line item's billing rule must be set to TriggerWithoutFulfillment
.
C3: Instruct Zuora Billing to invoice for an order line item partial shipment
Create a fulfillment that records a shipment using (Create fulfillments)[https://developer.zuora.com/v1-api-reference/api/operation/Create_Fulfillment/]:
curl -i -X POST --url 'https://rest.apisandbox.zuora.com/v1/fulfillments' \
-H "Authorization: Bearer $ztoken" \
-H "Content-Type: application/json" \
-d '{
"fulfillments": [
{
"fulfillmentDate": "2025-03-16",
"quantity": 11,
"description": "Example call for an ERP fulfillment",
"state": "SentToBilling",
"billTargetDate": "2025-03-16",
"orderLineItemId": "8ad08ea195911c9c019591eb1d506360",
"fulfillmentType": "Delivery",
"trackingNumber": "T-0009872",
"carrier": "UPS",
"fulfillmentSystem": "ERP",
"fulfillmentLocation": "Travis",
"externalId": "ERP-0987123"
}
]
}'
The response is similar to the following snippet:
{
"fulfillments" : [ {
"id" : "8ad0875995a3ed800195a6479f7b3fba",
"fulfillmentNumber" : "F-00000002",
"fulfillmentItems" : [ ]
} ],
"invoiceNumbers" : null,
"creditMemoNumbers" : null,
"paymentNumber" : null,
"paidAmount" : null,
"success" : true
}
The returned response shows several options for this call that we did not cover here. For example, you can ask for billing to be triggered immediately, or ask Zuora Billing to collect payment immediately once invoiced with the necessary conditions met.
If your ERP cannot make the Zuora Billing API calls described here, you can utilize our Zuora Platform Extension Studio Workflow add-on to query your ERP upon a schedule to see what has shipped. Contact your Zuora Account Team if you are unfamiliar with Workflow.
Step 5: Test and Validate Your Integration
-
Verify data flow
:
Ensure journal entries are correctly posted to your ERP system and that amounts match between Zuora and your ERP. -
Test for errors
:
Test for scenarios like invalid accounting period names or trial balance failures. Make sure errors are flagged for review.
Conclusion
Congratulations! You’ve completed a basic ERP Fulfillment integration with Zuora Billing. While this quickstart guide has focused on the basics, many more use cases, such as processing returns or RMAs are also supported. More on all our APIs, including tutorials, FAQs, a Developer Blog and reference documentation can be found in our Zuora Developer Center.