Sign up subscribers

Quickstart API
v1 API

Create a subscription with a customer account

Suppose that a new customer wants to subscribe to a service offered by you. You need to capture the following information:

  • Basic information about your new customer
  • The product or service you will be provisioning for them
  • Price and frequency with which they will be charged
  • The contract effective date from which the subscription becomes effective

By default the payment method will be authorized with the payment gateway you have configured for your tenant.

The following example shows how to create a subscription, passing the customer account and a reference to a plan. To learn about plans, see the Plans API operations.

cURLJavaNode
Copy
Copied
curl -X POST "https://rest.test.zuora.com/v2/subscriptions" 
     -H "Authorization: Bearer 6d151216ef504f65b8ff6e9e9e8356d3" 
     -H "Content-Type: application/json" 
     -d '{  
          "account_data":{
            "bill_to": {
                "first_name": "Amy",
                "last_name": "Lawrence",
                "email": "amy.lawrence@zuora.com",
                "address":{
                  "line1": "101 Redwood Shors Parkaway",
                  "city": "Redwood City",
                  "postal_code": "94065",
                  "state": "CA",
                  "country": "USA"
                }
            },
            "name": "Amy Lawrence Account",
            "currency": "USD"
          },
          "subscription_plans": [{
            "plan_id": "8ad095b8813772670181383d05136860"
          }],
          "start_on":{
            "contract_effective": "2022-08-01"
          }
        }'
Copy
Copied
AccountContactCreateRequest contactCreateRequest = new AccountContactCreateRequest()
    .firstName("Amy")
    .lastName("Lawrence")
    .email("amy.lawrence@zuora.com")
    .address(new Address()
               .line1("101 Redwood Shors Parkaway")
               .city("Redwood City")
               .postalCode("94065")
               .country("USA")
               .state("CA"));

AccountCreateRequest accountCreateRequest = new AccountCreateRequest()
    .name("Amy Lawrence's Account")
    .billTo(contactCreateRequest)
    .currency("USD");

PlanCreateRequest planRequest = new PlanCreateRequest() 
    .name('Monthly Plan') 
    .productId(newProduct.getId()) 
    .startDate('2021-10-20') 
    .endDate('2031-10-19') 
    .description('Gold Product'); 

Plan newPlan = zuoraClient.plans().createPlan(planRequest); 

LocalDate todayDate = LocalDate.now();
String todayDateStr = todayDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
SubscriptionCreateRequest subscriptionCreateRequest = new SubscriptionCreateRequest() 
  .accountData(accountCreateRequest) 
  .subscriptionPlans(Collections.singletonList(new SubscriptionChildPlanCreateRequest().planId(newPlan.getId())))
  .startOn(new StartOn().contractEffective(todayDateStr)); 

Subscription createdSubscription = zuoraClient.subscriptions().createSubscription(subscriptionCreateRequest);
Copy
Copied
const date = new Date();
const todayDate = date.toISOString().split('T')[0];
const planId = '8ad095b8813772670181383d05136860';
 
const account = {
  bill_to: {
    first_name: 'Amy',
    last_name: 'Lawrence',
    email: 'amy.lawrence@zuora.com',
    address:{
      line1: '101 Redwood Shors Parkaway',
      city: 'Redwood City',
      postal_code: '94065',
      state: 'CA',
      country: 'USA',
    }
},
name: 'Amy Lawrence Account',
currency: 'USD',
}
 
const subscriptionRequest = {
    account_data: account,
    subscription_plans: [
      {
        plan_id: planId,
      }
    ],
    start_on:{
      contract_effective: todayDate,
    },
};

const createdSubscription = await zuoraClient.subscriptions.createSubscription(subscriptionRequest);

Preview a subscription

You can use the "Preview a subscription" operation to generate a preview of billing documents and charge metrics of a subscription. This operation is only for preview, and no subscription or billing document is created. You can use this operation to the following metrics generated by the subscription:

  • Metrics on the billing documents, including:
    • Total amount
    • Subtotal amount
    • Tax amount
  • Delta metrics of order actions, including:
    • Gross amount of delta MRR
    • Net amount of delta MRR
For more information about the Order delta metrics, see Order Delta Mrr.

To preview a subscription, you must specify the following fields:

  • account_id or account_data
  • metrics
  • subscription_plans
The following example previews the billing document metrics for an evergreen subscription (subscription plan ID is 8ad09bce82aa84840182afab5e7b04fb) where the ID of the associated account is 8ad09b7d8292b85d0182a4d6f875225a:
cURLJavaNode
Copy
Copied
curl --request POST
     --url 'https://rest.test.zuora.com/v2/subscriptions/preview'
     --header 'Authorization: Bearer 2e4e1763af7d4cf5aaca1b519dfa3200'
     --header 'Content-Type: application/json'
     --data '{
        "account_id": "8ad09b7d8292b85d0182a4d6f875225a",
        "subscription_plans": [
          {
            "plan_id": "8ad09bce82aa84840182afab5e7b04fb"
          }
        ],
        "end_date": "2022-11-30",
        "metrics": ["billing_documents"]
      }'
Copy
Copied
LocalDate date = LocalDate.of(2022,11,30);

SubscriptionPreviewRequest previewRequest = new SubscriptionPreviewRequest()
  .metrics(Collections.singletonList(SubscriptionPreviewRequest.MetricsEnum.BILLING_DOCUMENTS))
  .endDate(date)
  .accountId("8ad09b7d8292b85d0182a4d6f875225a")
  .subscriptionPlans(Collections.singletonList(new SubscriptionPlanCreateRequest().planId("8ad09bce82aa84840182afab5e7b04fb")));

Map<String, Object> previewSubscription = zuoraClient.subscriptions().previewSubscription(previewRequest); 
System.out.println(previewSubscription);
Copy
Copied
const previewRequest = {
    account_id: '8ad09c4b84eac7870184ec0b170f1d87',
    subscription_plans: [
      {
        plan_id: '8ad09bce82aa84840182afab5e7b04fb'
      }
    ],
    end_date: '2023-4-30',
    metrics: ['billing_documents']
};
 
const previewSubscription = await zuoraClient.subscriptions.previewSubscription(previewRequest);
console.log(previewSubscription);

Update subscriptions

After you have created subscriptions, you can make modifications to the created subscriptions. This article provides common use cases on updating subscriptions and the corresponding code samples.

If you want to make changes to the subscription, you can use the Update a subscription operation to update the subscription. You can add subscription plans, remove subscription plans, change subscription plan details, or renew subscriptions by specifying the following fields, respectively:

  • add_subscription_plans
  • remove_subscription_plans
  • update_subscription_plans
  • renew

Add a subscription plan to a subscription

The following example provides an example of updating a subscription by adding a new plan to the created subscription.

cURLJavaNode
Copy
Copied
curl -X PATCH "https://rest.test.zuora.com/v2/subscriptions/8ad08f74803a5e3e01803f340e3c2148"
  -H "Authorization: Bearer 6d151216ef504f65b8ff6e9e9e8356d3" 
  -H "Content-Type: application/json" 
  -d '{ 
        "description": "Updated subscription description",
        "add_subscription_plans": [{
          "subscription_plan":{ 
            "plan_id": "8ad09bce8292b8480182a8ea00db35b3",
            "prices":[{
               "price_id": "8ad095b882aa84850182abbe78fd12f1"
             }]
          },
          "start_on": {
             "contract_effective": "2022-08-01",
             "service_activation": "2022-08-01",
             "customer_acceptance": "2022-08-01"
          }
       }]
      }'
Copy
Copied
LocalDate date = LocalDate.of(2022,8,20);
String oldSubscriptionId = subscription.getId();

SubscriptionItemCreateRequest subscriptionItemCreateRequest = new SubscriptionItemCreateRequest().priceId("8ad095b882aa84850182abbe78fd12f1");

SubscriptionPlanCreateRequest subscriptionPlanRequest = new SubscriptionPlanCreateRequest()
  .planId("8ad09bce8292b8480182a8ea00db35b3")
  .prices(Collections.singletonList(subscriptionItemCreateRequest));

SubscriptionAddPlanPatchRequest addSubscriptionPlanRequest = new SubscriptionAddPlanPatchRequest()
  .subscriptionPlan(subscriptionPlanRequest)
  .startOn((new StartOn()
    .contractEffective(date)
    .customerAcceptance(date)
    .serviceActivation(date)));

SubscriptionPatchRequest updateRequest = new SubscriptionPatchRequest()
  .addSubscriptionPlans(Collections.singletonList(addSubscriptionPlanRequest));

Subscription updatedSubscription = zuoraClient.subscriptions().patchSubscription(oldSubscriptionId,updateRequest);
Copy
Copied
const updatedSubscription = await zuoraClient.subscriptions.patchSubscription('8ad08f74803a5e3e01803f340e3c2148',
   {
     description: 'Add a subscription plan',
     add_subscription_plans: [{
       subscription_plan:{  
          plan_id: '8ad09bce8292b8480182a8ea00db35b3',
          prices:[{
            price_id: '8ad095b882aa84850182abbe78fd12f1',
          }],
       },
       start_on: {
         contract_effective: '2022-12-31',
       }
     }],
   }
 );

Remove a subscription plan from a subscription

You can also remove a subscription plan from an existing subscription with the Update subscription API operation.

The following code samples provide an example of removing a subscription plan from a created subscription:

cURLJavaNode
Copy
Copied
curl -X PATCH "https://rest.test.zuora.com/v2/subscriptions/8ad08f74803a5e3e01803f340e3c2148"
     -H "Authorization: Bearer 6d151216ef504f65b8ff6e9e9e8356d3" 
     -H "Content-Type: application/json" 
     -d '{ 
            "description": "Remove a subscription plan",
            "remove_subscription_plans": [ {
            "subscription_plan_id": "8ad08ccf82afa5d70182afdb2242002f", 
            "start_on": { 
                "contract_effective": "2022-08-20",
                "service_activation": "2022-08-20", 
                "customer_acceptance": "2022-08-20" 
            }
            }]
        }'
Copy
Copied
LocalDate removePlanDate = LocalDate.of(2022,8,20);
String oldSubscriptionId = createdSubscription.getId();

SubscriptionRemovePlanPatchRequest removeSubscriptionPlanRequest = new SubscriptionRemovePlanPatchRequest()
    .subscriptionPlanId("8ad09b7d80936cd1018098c227be79e4")
    .startOn((new StartOn()
        .contractEffective(removePlanDate)
        .customerAcceptance(removePlanDate)
        .serviceActivation(removePlanDate)));

SubscriptionPatchRequest updateRequest = new SubscriptionPatchRequest().removeSubscriptionPlans(Collections.singletonList(removeSubscriptionPlanRequest));

Subscription updatedSubscription = zuoraClient.subscriptions().patchSubscription(oldSubscriptionId,updateRequest);
Copy
Copied
const updatedSubscription = await zuoraClient.subscriptions.patchSubscription('8ad08f74803a5e3e01803f340e3c2148',
   {
     description: 'Remove a subscription plan',
     remove_subscription_plans: [{
        subscription_plan_id:'8ad08ccf82afa5d70182afdb2242002f',
        start_on: {
          contract_effective: '2022-12-31',
        },
     }],
   }
);

Update the product quantity on a subscription

You can update the product quantity on a subscription only if the product uses the following prices:

  • Per-unit
  • Tiered

If you request to update the product quantity for other prices, the request will result in an error.

In this scenario, you need to specify the following fields in the update_subscription_plans > subscription_plan > subscription_items nested object for the "Update a subscription" operation:
  • quantity
  • start_date
The following example updates the quantity field of a subscription item to 25 and the unit_amount to 40.
cURLJavaNode
Copy
Copied
curl --request PATCH \
  --url 'https://rest.test.zuora.com/v2/subscriptions/A-S00013513' \
  --header 'Authorization: Bearer 2d152847628046fca3ff3c63540933e3' \
  --header 'Content-Type: application/json' \
  --data '{
            "update_subscription_plans": [
		    {
                "subscription_plan": {
                    "subscription_plan_id": "8ad08e0183babdd00183c602861670cf",
                    "subscription_items": [
                        {
                            "id": "8ad08e0183babdd00183c602861670d0",
                            "quantity": 25,
                            "unit_amount": 40,
                            "start_date": "2022-10-10"
                        }
                    ]
                },
                "start_on": {
                    "contract_effective": "2022-10-10",
                    "service_activation": "2022-10-10",
                    "customer_acceptance": "2022-10-10"
                }
		    }
	        ]
	    }'
Copy
Copied
LocalDate date = LocalDate.of(2022,10,10);
String subscriptionId = createdSubscription.getId();

SubscriptionItemPatchRequest subscriptionItemCreateRequest = new SubscriptionItemPatchRequest()
    .id("8ad08e0183babdd00183c602861670d0")
    .quantity(new BigDecimal(25))
    .unitAmount(new BigDecimal(40))
    .startDate(date);

List<SubscriptionItemPatchRequest> subscriptionItems = new ArrayList<>();
subscriptionItems.add(subscriptionItemCreateRequest);

SubscriptionPlanPatchRequest subscriptionPlanRequest = new SubscriptionPlanPatchRequest()
    .subscriptionPlanId("8ad08e0183babdd00183c602861670cf")
    .subscriptionItems(subscriptionItems);

SubscriptionUpdatePlanPatchRequest updateSubscriptionPlanRequest = new SubscriptionUpdatePlanPatchRequest()
    .subscriptionPlan(subscriptionPlanRequest)
    .startOn((new StartOn().contractEffective(date)));

List<SubscriptionUpdatePlanPatchRequest> subscriptionPlans = new ArrayList<>();
subscriptionPlans.add(updateSubscriptionPlanRequest);

SubscriptionPatchRequest updateRequest = new SubscriptionPatchRequest().updateSubscriptionPlans(subscriptionPlans);

Subscription updatedSubscription = zuoraClient.subscriptions().patchSubscription(subscriptionId,updateRequest);

System.out.println(updatedSubscription);
Copy
Copied
const updatedSubscription = await zuoraClient.subscriptions.patchSubscription('8ad08e0183babdd00183c60285e970ca',
 {
   description: "Remove a subscription plan",
   update_subscription_plans: [{
      subscription_plan:{
        subscription_plan_id:'8ad08e0183babdd00183c602861670cf',
        subscription_items:[
        {
          id: "8ad08e0183babdd00183c602861670d0",
          quantity: 25,
          unit_amount: 40,
          start_date: '2022-10-10',
        }
        ]
      },
      start_on: {
        contract_effective: '2022-12-31',
      }
   }],
 }
);

Cancel a subscription

When an end subscriber decides to terminate their subscription, there are three ways for the merchant to manage billing:

  • Cancel the subscription and make the cancellation effective after the last invoiced periodAfter the cancellation, billing will stop immediately for the subscription. The cancellation is effective after the latest invoice through date. To use this option for subscription cancellation, set the cancel_at field to invoice_period_end.
  • Cancel the subscription and make the cancellation effective at the end of the current subscription term.

    This option is applicable only to termed subscriptions. After the cancellation, billing will continue until the end of the current subscription term and then stop. If the subscription is set to auto-renew when the subscription is created, the auto-renewal will be stopped when the subscription is canceled.

    To use this option for subscription cancellation, set the cancel_at field to subscription_term_end.
  • Cancel the subscription and make the cancellation effective on a specific date
    • If the cancellation is made effective during a service period that has already been billed, Zuora will credit back the prorated amount from the cancellation effective date.
    • If the cancellation is made effective after the billed through date, Zuora will continue to bill until the cancellation effective date. After that, billing will stop.
    To use this option for subscription cancellation, set the cancel_date field to a specific date.

    The following code example demonstrates how to cancel a subscription at the end of billing period while specifying the processing option:

cURLJavaNode
Copy
Copied
curl --request PATCH \
     --url 'https://rest.test.zuora.com/v2/subscriptions/​​A-S00000035/cancel' \
     --header 'Authorization: Bearer 6d151216ef504f65b8ff6e9e9e8356d3' \
     --header 'Content-Type: application/json'\
     --data '{
                "cancel_at": "invoice_period_end",
                "processing_options": {
                    "collection_method": "collect_payment",
                    "document_date": "2022-09-01"
                }
             }'
Copy
Copied
LocalDate documentDate = LocalDate.of(2022,9,1);
String subscriptionNumber = "A-S00013446";

CancelSubscriptionRequest cancelRequest = new CancelSubscriptionRequest()
    .cancelAt(CancelAtEnum.INVOICE_PERIOD_END)
    .processingOptions(new ProcessingOptions()
        .documentDate(documentDate)
        .collectionMethod(CollectionMethodEnum.COLLECT_PAYMENT));

Subscription canceledSubscription = zuoraClient.subscriptions().cancelSubscription(subscriptionNumber,cancelRequest);
Copy
Copied
const canceledSubscription = await zuoraClient.subscriptions.cancelSubscription('8ad0950c8480aa70018482ce8706460f', 
    {
      cancel_at: 'invoice_period_end',
      processing_options: {
        document_date: '2022-09-01',
        collection_method: 'create_invoice'
      }
    }
);

Update contact information for an account

Zuora requires two types of contacts to be associated with an account: bill-to contact and sold-to contact.

The bill-to contact determines where the invoice should be delivered, whereas the sold-to contact determines how taxes are calculated. If the invoice delivery preference is email, the bill-to contact must contain an email address.

In this use case, we will update the sold-to contact information of an account using the Update an account operation.

cURLJavaNode
Copy
Copied
curl --request PATCH
     --url https://rest.test.zuora.com/v2/accounts/2c92c0f86a8dd422016a9e7a70116b0d 
     --header 'Authorization: Bearer 06a297740b184fc384bc57cbe8a04e53'
     --header 'Content-Type: application/json'
     --data '{
               "sold_to":{
                   "first_name": "Jane",
                   "last_name": "Doe",
                   "address": {
                       "line1": "No.111, Street ABC",
                       "city": "San Francisco",
                       "state": "CA",
                       "country": "United States"
                    }
                }
     }'
Copy
Copied
String accountId = "2c92c0f86a8dd422016a9e7a70116b0d";

Address soldToAddress = new Address()
    .line1("No.123, Street ABC")
    .city("San Francisco")
    .state("CA")
    .country("United States");

AccountPatchRequest accountPatchRequest = new AccountPatchRequest()
    .soldTo(new AccountContactPatchRequest()
        .firstName("Jane")
        .lastName("Doe")
        .address(soldToAddress));

Account updatedAccount = zuoraClient.accounts().updateAccount(accountId,accountPatchRequest);
Copy
Copied
const accountId = '2c92c0f86a8dd422016a9e7a70116b0d';
 
const accountPatchRequest = {
    sold_to:{
        first_name: 'John',
        last_name: 'Doe',
        address: {
            country: 'United States',
            state: 'CA',
            city: 'San Francisco',
            line1: 'No.111, Street ABC'
        }
    }
};
 
const updatedAccount = await zuoraClient.accounts.updateAccount(accountId, accountPatchRequest);