Billing Usage
In this walkthrough, we're going to follow two Zuora API users, Boris and Natasha, as they upload usage records in preparation for a bill run. Someone else created the rate plans with usage charges and customers subscribed to these rate plans some time ago. You can use Boris and Natasha's code samples to customize their actions to fit your own needs.
Learning Path for Advanced API Users
If you are an advanced API user, then you might want to review only Implementation sections of this walkthrough to get a quick list of the steps for uploading usage data without the additional details:
Usage and Tracking Metered Resources
Usage is the amount of resources a customer uses. You track the usage of metered resources, then charge based on the amount that your customers consume.
You can charge for usage by adding usage-based fees to product rate plans, tracking usage, then uploading usage records to Zuora.
You can set up rate plans to include all types of charges: one-time fees, recurring fees, and usage fees. Of these charges, usage-based fees require you to meter your customers' usage and upload that data to Zuora so that Zuora can calculate the charges.
Billing usage allows you to bill users according to their actual use of your resources; when their usage levels vary, so do their bills. As such, usage is always billed in arrears. For example, you bill in November for usage consumed in October, or you bill in the fourth quarter for usage consumed in the third quarter. You can bill usage on a recurring, monthly, quarterly, semi-annual, and annual basis.
If the number of usage records that you need to upload is 50 or fewer, then you can use the create() call with a Usage object to do the upload. If you need to upload a larger number of usage records, then you need to create a CSV file of 4MB or smaller, and upload that file with the create() call and an Import object.
Upload Best Practices
Consider the size of your upload, and consider your company's best practices for usage data association before you start an upload.
Upload size
There are two ways to upload usage data, both using the create() call. You can use the Usage object to send up to 50 records in a single call. That method works well when you don't have a lot of data to upload. However, the method is cumbersome with more than 50 records because you need to do the upload through a series of bath calls. When you have a large set of data, especially more than 50 records, use the Import object instead of the Usage object.
This walkthrough follows both methods of uploading usage. To use the Usage object, follow Boris. To use the Import object, follow Natasha.
Associate Usage Records with Accounts, Charges, or Subscriptions
Widget Mail has a best practice require to connect usage data with a specific subscription. To meet this requirement, Boris and Natasha need to use either the SubscriptionId
or the SubscriptionNumber
field for each Usage object.
You might also have requirements to specific subscriptions or charges.
Use the ChargeId
or ChargeNumber
field to connect usage to its charge. Use SubscriptionId
or SubscriptionNumber
to apply usage data to all charges with the same unit of measure in the subscription.
If you omit all of the fields ChargeId
, ChargeNumber
, SubscriptionId
, and SubscriptionName
, then usage is billed against all charges associated with the account that have the same UOM
values. The two charge-related fields, ChargeId
and ChargeNumber
, connect usage with a specific charge. The two subscription-related fields, SubscriptionId
and SubscriptionName
, connect usage with a specific subscription.
You only need one charge-related field or one subscription-related field to connect the usage data to a specific charge or subscription; you don't need both the ID and the number fields.
Upload a Small Number of Usage Records
Boris is a Zuora API user who works for Widget Mail, which provides an email infrastructure in the cloud. His company offers plans that include both recurring fees and usage-based fees. Monthly recurring fees include a base number of emails with a per-email tiered set of charges over this default amount.
Boris needs to import a set of usage records so that the data is ready for a scheduled bill run.
Solution
Boris has three usage records to upload. He decides to use a create() call with the Usage object, which can send up to 50 records in a single call.
Preparation
Boris gathers the following information about each record:
- Account ID (
AccountId
): required by Zuora - Quantity of units used (
Quantity
): required by Zuora - Units of measure (
UOM
): required by Zuora - Start date and time of usage (
StartDateTime
): required by Zuora - End date and time of usage (
EndDateTime
) - Subscription ID (
SubscriptionId
)
Each of these items corresponds to a field in the Usage object that he needs to pass in the create() call. Not all of these bits of information are required by Zuora, but he needs to provide optional fields to meet the requirements of Widget Mail's own processes. Your company might have its own best practices that require you to use fields that are not otherwise required by the API.
Field Descriptions
The example values are the values that Boris uses in his code sample. If you use his code samples, then substitute your own values. Because Boris is uploading three sets of usage data, he is creating three Usage objects. Each object has its own set of values.
Name | Required? | Description |
---|---|---|
AccountId | required |
The ID of the account associated with the usage data. Boris must provide a value for either the Type: zns:ID Example values:
|
EndDateTime | optional | The end date of a range of time during which usage is tracked. The Zuora API doesn't require this field because it doesn't need this field to calculate usage. However, Widget Mail uses this field for its reports so Widget Mail's best practices require Boris to include this value.
Type:
Character limit: 29 Example values:
|
Quantity | required | Indicates the number of units used. This number is the point of uploading usage data because it tells Zuora how much of a metered rescource was used.
Type: decimal Example values:
|
StartDateTime | required | The start date of a range of time during which usage is tracked.
Type: dateTime Example values:
|
SubscriptionId | optional | The ID of the subscription that contains the fees related to the usage data. This field connects usage with a specific subscription. Widget Mail's best practices require Boris to connect usage to specific subscriptions.
Type: zns:ID Example values:
|
UOM | required | Specifies the units to measure usage. Units of measure are configured in the web-based UI. Your values depend on your configuration in Z-Billing > Settings.
Type: string Example values
|
Implementation with the Usage object
Boris sends his create()
call with three Usage
objects.
Code sample: create three Usage objects
<ns1:create> <ns1:zObjects xsi:type="ns2:Usage"> <ns2:AccountId>4028z596336e2e6g1233773ge7c5011c8</ns2:AccountId> <ns2:EndDateTime>2012-11-30T15:00:00</ns2:EndDateTime> <ns2:Quantity>2548533</ns2:Quantity> <ns2:StartDateTime>2012-10-01T15:00:00</ns2:StartDateTime> <ns2:SubscriptionId>4028e6962eb8004a012ebd076551723a</ns2:SubscriptionId> <ns2:UOM>Each</ns2:UOM> </ns1:zObjects> <ns1:zObjects xsi:type="ns2:Usage"> <ns2:AccountId>4028g485225d1d5f01247692fd6b249j9</ns2:AccountId> <ns2:EndDateTime>2012-11-30T15:00:00</ns2:EndDateTime> <ns2:Quantity>8944</ns2:Quantity> <ns2:StartDateTime>2012-10-01T15:00:00</ns2:StartDateTime> <ns2:SubscriptionId>402892ca29f3191a0129f31a86ad00ac</ns2:SubscriptionId> <ns2:UOM>Each</ns2:UOM> </ns1:zObjects> <ns1:zObjects xsi:type="ns2:Usage"> <ns2:AccountId>4028e718548p7h9b73401849fd6b249c3</ns2:AccountId> <ns2:EndDateTime>2012-11-30T15:00:00</ns2:EndDateTime> <ns2:Quantity>26541</ns2:Quantity> <ns2:StartDateTime>2012-10-01T15:00:00</ns2:StartDateTime> <ns2:SubscriptionId>4028e6992276b15101228441bf7531ce</ns2:SubscriptionId> <ns2:UOM>Each</ns2:UOM> </ns1:zObjects> </ns1:create>
After successful completion of the call, Boris receives a response that includes the IDs of the new Usage
objects. Your values differ from his because IDs are unique.
Upload a Large Number of Usage Records
Natasha is a Zuora API user who works for Widget Mail, which provides an email infrastructure in the cloud. Her company offers plans that include both recurring fees and usage-based fees. Monthly recurring fees include a base number of emails with a per-email tiered set of charges over this default amount.
Natasha needs to import a large set of usage records so that the data is ready for a scheduled bill run.
Solution
Natasha has a large set of usage data, so she decides to use a create()
call with the Import
object, which can load a CSV
file up to 4MB in a single call.
The number of records that can fit in a 4MB CSV
file depends on the size of your dataset. If you are using all of the fields at maximum character size, then your number of records is smaller than someone else's number who is using just the Zuora-required fields.
Preparation
Natasha receives a CSV
file that contains all the information she needs about each record. Each field in the file corresponds to a field that Zuora needs to record usage. These fields have similar names as the fields that Boris used when he uploaded a small number of records with the Usage
object, but they aren't identical. Check the field names in your CSV
file to make sure they're correct.
- Account ID (
ACCOUNT_ID
): required by Zuora - Units of measure (
UOM
): required by Zuora - Quantity of units used (
QTY
): required by Zuora - Start date of usage (
StartDate
): required by Zuora - End date of usage (
EndDate
) - Subscription ID (
SUBSCRIPTION_ID
) - Charge ID (
CHARGE_ID
) - Description (
DESCRIPTION
)
Not all of these bits of information are required by Zuora. Natasha omits data for the charge ID and description fields because they are optional in Zuora and Widget Mail's best practices don't use them. However, Natasha does use the fields for the subscription ID and end date because these fields, while optional in Zuora, are requirements of Widget Mail's own processes. Your company might have its own best practices that require you to use fields that are not otherwise required by the API.
Field descriptions
The example values are the values that Natasha uses in her code sample. If you use her code samples, then substitute your own values.
These field descriptions are specifically for the Import object, not the fields in Natasha's CSV file.
Name | Required? | Description |
---|---|---|
FileContent | required | A Base64-encoded file that contains the contents of the import. Type: DataHandler Example value: zuora-usage.csv |
ImportType | required | The type of item that you want to import. Natasha is importing usage records. Type: string (enum) Example value: Usage |
Name | required | A descriptive name for the import operation. Natasha calls her import Nov2012 because it's Widget Mail's best practice to name usage imports by the name of the month of the usage data's date range. Your value depends on your own policies. You can leave the field value empty to use the default, import <ImportType_value> . Type: string Example value: Nov2012 |
Implementation with the Import object
Natasha sends her create()
call for one Import
object to import a single CSV
file that contains many usage records.
Code sample: create one Import object
<ns1:create> <ns1:zObjects xsi:type="ns2:Import"> <ns2:FileContent>zuora-usage.csv</ns2:FileContent> <ns2:ImportType>Usage</ns2:ImportType> <ns2:Name></ns2:Name> </ns1:zObjects> </ns1:create>
After successful completion of the call, Natasha receives a response that includes the ID of the new Import
object. Your value differs from hers because IDs are unique.
What next?
Boris and Natasha have uploaded all of the usage records needed for the next bill run. They can update the individual usage records if changes are needed. Otherwise, the usage records are ready to be billed during the next bill run or individual invoice generation.