Managing a subscription

If you're using Digital River's subscription service, gain a better understanding of how to manage subscriptions after the acquisition process is complete

If you're using Digital River's subscription service, you'll need to manage the subscription after completing the acquisition checkout process. On this page, you'll find information on how to:

Activating a subscription

After the order's state moves to accepted, you can activate a subscription. To do this, retrieve each items[].subscriptionInfo.subscriptionId from the data.object of the event with a type of order.accepted and send it as a path parameter in a POST /subscriptions/{subscriptionId}.

If you're using the Direct Integrations checkout solution, you could also get each items[].subscriptionInfo.subscriptionId from the body of the POST/ orders response.

In the body of the request, set state to active.

curl --location --request POST 'https://api.digitalriver.com/subscriptions/DR_3ce5dc58-6bba-4ee2-b8d1-e1b974a4fe93' \
...
--data-raw '{
    "state": "active"
}'

No other values can be sent in the body of this request. If you attempt to do so, then the following error is returned:

{
    "type": "conflict",
    "errors": [
        {
            "code": "restricted_update",
            "parameter": "metadata",
            "message": "Additional data cannot be updated when updating state to active."
        }
    ]
}

You can activate a subscription any time after an order's state moves to accepted. For example, if you're selling a digital service subscription that requires no provisioning, you might build your integration so that the activation request is immediately submitted. In other scenarios, such as when a customer must install and initialize a device, you may decide to build a delay into the activation process.

When you activate the subscription, we search the acquisition order for the primary payment source, retrieve its identifier, and assign that value to sourceId in the subscription object. On the next invoice date, we then both create a charge and attempt to capture payment using this reusable source.

After activation, the following key subscription attributes are populated: contractBindingUntil, nextReminderDate, currentPeriodEndDate, nextInvoiceDate, and activated.

Every subscription contains a billingAgreementId that references a billing agreement. For PSD2 and SCA compliance purposes, we continue to associate this billing agreement with the subscription throughout the subscription's lifecycle.

{
    "id": "47ce1ba0-a548-40a2-a601-a43c41fbe68f",
    "contractBindingUntil": "2023-02-09T17:40:56Z",
    "createdTime": "2022-02-09T17:40:21Z",
    "updatedTime": "2022-02-09T17:40:56Z",
    "stateTransitions": {
        "activated": "2022-02-09T17:40:56Z"
    },
    "billingAgreementId": "8f1ef7b9-e5c5-46d1-ac14-1c9d566f0f57",
    "customerId": "562799360336",
    "sourceId": "1fc4353a-e1ab-476b-8ebd-db181c1a21a7",
    "taxInclusive": false,
    "currency": "USD",
    "planId": "82cbf763-fa27-401a-aa69-5e6640539ce7",
    "state": "active",
    "items": [
        {
            "price": 100.0,
            "skuId": "865a15d2-4e00-4c09-8813-7b82a078491b",
            "quantity": 1
        }
    ],
    "currentPeriodEndDate": "2022-03-09T17:40:56Z",
    "nextInvoiceDate": "2022-03-04T17:40:56Z",
    "nextReminderDate": "2022-02-27T17:40:56Z",
    "liveMode": false
}

Fulfilling the acquisition

Once the order's state is accepted, you should fulfill the goods and then submit the payment capture request.

Notifying customers of a subscription acquisition

Once a subscription is successfully acquired, you can use the event with a type of order.accepted to trigger an acquisition confirmation notification.

Renewing subscriptions

On a subscription's nextReminderDate, make sure you send a renewal reminder to customers. Your integration should also be able to handle both successful and failed billing attempts.

Sending a reminder

Before attempting to collect a recurring payment, our subscription service determines whether the necessary pre-conditions are met. If they are, the service opens a draft invoice and, on the subscription's nextRemiderDate, creates an event with a type of subscription.reminder.

You can configure when you receive this event by setting the plan's reminderOffsetDays.

The event's data.object contains the subscription along with an invoice .

Use the event's data to obtain the customer's contact information and populate your renewal reminder notification. This notification (typically an email) should include the subscription's name and a description of its goods, the amount the customer is to be charged, and the upcoming billing date.

A complete list of renewal reminder requirements is included in the Subscription Notifications article (refer to Learning tools for access information).

In invoice.items[].productDetails you can access the subscription's product data (such as name, description, image, and url) and pass this information to customers in the notification, thereby making them aware of what they're being billed for.

There are numerous ways to build your notification. However, we suggest that you convert any date-time values into a more human-readable form. The following are some (partial) examples of what you might add:

This is a reminder that your invoice.description subscription is set to renew on or after nextInvoiceDate. To ensure that your subscription continues without interruption, your creditCard.brand credit card ending in creditCard.lastFourDigits will be charged invoice.totalAmount in invoice.currency .

For digital services (such as SaaS), you might also want to include the date and time that customers activated their subscription:

You activated your subscription via our online store on stateTransitions.activated.

Additionally, we suggest you use the reminder event to determine whether the subscription's designated credit card is set to expire before the nextInvoiceDate. If this is the case, remind customers to update their payment information and provide a link to the appropriate page on your site. For example:

We noticed that your credit card ending in lastFourDigits is set to expire expirationMonth , expirationYear. This expiration date is prior to your next recurring payment on nextInvoiceDate. To avoid disruptions to your subscription, please visit your account management page and update your payment information.

Handling successful renewals

To be notified of a successful billing attempt, configure a webhook to listen for the event with a type of subscription.extended.

The event's data.object contains the subscription along with the invoice used to capture payment. Since settlement has successfully occurred, the invoice's state is paid.

You could handle subscription.extended by calling a function that moves the subscription in your system into a ready to fulfill state and then initiates the fulfillment process.

The event should also trigger a renewal confirmation message that gets sent to the customer. The following is a partial list of the data you might retrieve from the event and pass in this notification:

  • orderId: Gives customers access to the identifier of the transaction's order.

  • nextInvoiceDate: Provides customers with the date of the next billing attempt.

  • name and image in items[].productDetails: Reminds customers what products and/or services are included in the subscription.

  • payment.sources[]: Contains source data that you can share with customers so they have basic information on what payment method is funding the subscription.

  • totalAmount and totalTax: Informs customers how much they were charged and taxed. The event also contains similar amounts at the items[]-level.

The Subscription Notifications article (refer to Learning tools for access information) provides a comprehensive list of the information you're required to include in the renewal notification.

Handling failed renewals

To be notified of renewal problems, you can configure a webhook(s) to listen for:

Invalid sources and lapsed subscriptions

If Digital River can't create a billing invoice because there's a problem with the subscription's saved source (in the case of credit cards, this is often an invalid expiration date), then we create an event with a type of subscription.invalid_source.

We recommend handling it by informing shoppers that their subscription is at risk of cancellation, requesting a different payment method from them, and then, assuming they provide this information, updating the subscription's source.

If you don't make this update during the grace period (i.e., the collectionPeriodDays of the subscription’s plan), then Digital River moves the subscription’s state to lapsed and creates subscription.lapsed.

Since this is a terminal state, reactivating the subscription isn't possible, which means you'll likely want to discontinue customers' access to the service and provide instructions on how to restore it.

Payment failures

An event with a type of subscription.payment_failed indicates that Digital River's autorenewal service made an unsuccessful attempt to capture payment.

The event's data.object contains both the subscription and the invoice.

The event most likely stems from changes to the subscription's payment source. For example, if a subscription is funded with a credit card, its billing address could have changed, the customer might have cancelled it, or it might have reached its credit limit.

However, since the state of the subscription remains activePendingInvoice, you might still be able to collect payment.

Whatever the structure of your dunning process, we recommend you handle subscription.payment_failed by using the event's data.object to construct a billing failed notification that:

  • Informs customers of the failed payment capture attempt. For example: We were unable to charge your creditCard.brand ending in creditCard.lastFourDigits.\

  • Provides a link to a page on your site where customers can resolve the issue. For example: To avoid disruptions to your subscription, please visit your account management page.\

  • Provide your contact information. For example: If you have any questions, visit our support site at <web address>, contact us at <email address>, or call <phone number>.

If customers click the link, redirect them to a page where they can provide a new payment method.

For details, refer to Account management flows on the Building payment workflows page.

Once you create a new source or authenticate an existing source, you must associate it with the customer.

You'll also need to pass the source's identifier in the body of an update subscription request.

curl --location --request POST 'https://api.digitalriver.com/subscriptions/9a1f34b3-a5f5-4c5d-ab04-9a021b97a26d' \
...
--header 'Authorization: Bearer <Your secret API key>' \
...
--data-raw '{
	"sourceId": "19f15727-0712-473a-8b78-cc627efc0dfc"
}'

Before the next billing attempt, Digital River voids the invoice that we couldn't collect and creates a new invoice using the subscription's updated source.

Subscription failures

An event with a type of subscription.failed indicates that our autorenewal service was unable to capture payment during the designated collection period. As a result, the invoice has become uncollectible and the subscription has moved into a terminally failed state.

We recommend you handle subscription.failed by setting the status of the subscription in your own system to failed as well.

You should also send customers a failure notification that provides them the ability to reactivate their subscription. If customers select this option, you'll need to take them through the acquisition process again.

For example, the notification might:

  • Inform customers of the failed renewal. Despite repeated attempts, we were unable to charge your designated payment method, and as a result, your subscription has been deactivated. \

  • Provide a link to the page on your site where customers can resolve the issue. To reactivate your subscription, please visit your account management page. \

  • Provide your contact information. If you have any questions, visit our support site at <web address>, contact us at <email address>, or call <phone number>.

Trial subscription management

In this section, you'll find information on:

Activating trial subscriptions

You can use the same process to activate both trial and non-trial subscriptions. For details, refer to Activating a subscription.

curl --location --request POST 'https://api.digitalriver.com/subscriptions/124eeee4-6cf4-40e9-94a6-cba64798fc42' \
...
--data-raw '{
	"state": "active"
}'

Once activated, a free trial subscription's state transitions from draft to activeFree and the activatedFree timestamp is populated.

Subscription
{
    "id": "124eeee4-6cf4-40e9-94a6-cba64798fc42",
    "contractBindingUntil": "2022-02-18T15:03:12Z",
    "createdTime": "2022-02-11T15:01:31Z",
    "updatedTime": "2022-02-11T15:03:12Z",
    "stateTransitions": {
        "activatedFree": "2022-02-11T15:03:12Z"
    },
    "billingAgreementId": "6e4d986e-c054-43e0-a233-d6c1e9f60765",
    "customerId": "563089630336",
    "sourceId": "8687447b-a04d-4838-af6c-0de0810f23a7",
    "taxInclusive": false,
    "currency": "USD",
    "planId": "186cf07e-a1ea-4ec0-9d9a-8aa93b3af43a",
    "locale": "en_US",
    "state": "activeFree",
    "items": [
        {
            "price": 0.0,
            "skuId": "sku_3e5ab173-d52e-4d9e-8888-2a00f6bb188e",
            "quantity": 2
        }
    ],
    "currentPeriodEndDate": "2022-02-18T15:03:12Z",
    "nextInvoiceDate": "2022-02-18T15:03:12Z",
    "nextReminderDate": "2022-02-15T15:03:12Z",
    "liveMode": false
}

Updating the subscription's price and plan

Immediately following a successful activation request, we recommend that your integration use a POST /subscriptions/{id} to (1) update the subscription's planId so that it references a paid period plan and, (2) for each items[], set the price or aggregatePrice equal to the post-trial period amount that customers agreed to pay during the subscription acquisition process.

POST/ subscriptions/{subscriptionId}
curl --location --request POST 'https://api.digitalriver.com/subscriptions/124eeee4-6cf4-40e9-94a6-cba64798fc42' \
...
--data-raw '{
    "planId": "f55d07a2-a78f-406a-b6c6-ad8e1cc1531b",
    "items": [
        {
            "price": 29.95,
            "skuId": "sku_3e5ab173-d52e-4d9e-8888-2a00f6bb188e",
            "quantity": 2
        }
    ]
}'

After you submit this request, the subscription's planId references the paid period plan. However, until currentPeriodEndDate elapses, the trial period plan controls the subscription's behavior.

Subscription
{
    "id": "124eeee4-6cf4-40e9-94a6-cba64798fc42",
    "contractBindingUntil": "2022-02-18T15:03:12Z",
    "createdTime": "2022-02-11T15:01:31Z",
    "updatedTime": "2022-02-11T15:05:08Z",
    "stateTransitions": {
        "activatedFree": "2022-02-11T15:03:12Z"
    },
    "billingAgreementId": "6e4d986e-c054-43e0-a233-d6c1e9f60765",
    "customerId": "563089630336",
    "sourceId": "8687447b-a04d-4838-af6c-0de0810f23a7",
    "taxInclusive": false,
    "currency": "USD",
    "planId": "f55d07a2-a78f-406a-b6c6-ad8e1cc1531b",
    "locale": "en_US",
    "state": "activeFree",
    "items": [
        {
            "price": 29.95,
            "skuId": "sku_3e5ab173-d52e-4d9e-8888-2a00f6bb188e",
            "quantity": 2
        }
    ],
    "currentPeriodEndDate": "2022-02-18T15:03:12Z",
    "nextInvoiceDate": "2022-02-18T15:03:12Z",
    "nextReminderDate": "2022-02-15T15:03:12Z",
    "liveMode": false
}

On the nextReminderDate, Digital River creates an event whose type is subscription.reminder and whose data.object contains an invoice in a draft state.

Assuming you updated the subscription's items[].price or items[].aggregatePrice, the invoice's totalAmount will be greater than zero and equal to the aggregated price of all the subscription's items[], plus taxes and fees calculated by Digital River.

This totalAmount is how much customers will be charged for the subscription's nextInvoiceDate, which (if you configured your trial period plan correctly) should be the same as the currentPeriodEndDate. In other words, customers won't be charged until the free trial period is over.

Handling trial conversions

Before a trial converts to a paid subscription, you should send customers an expiration reminder. After a successful conversion occurs, make sure you also send a conversion notification.

Sending a free trial expiration reminder

We recommend that you use subscription.reminder to trigger an email (or some other type of notification) to the customer. In the event's payload, currentPeriodEndDate, nextInvoiceDate, and totalAmount provide the data you need to inform customers (1) on what date their free trial is scheduled to expire, (2) when their first payment is scheduled, and (3) in what amount.

Sending a trial conversion notification

On the nextInvoiceDate, Digital River moves the invoice to open and the subscription to activePendingInvoice and then attempts to collect payment for the number of days specified by the trial period plan's collectionPeriodDays.

If any of these collection attempts are successful, Digital River marks the invoice as paid and the subscription as active, populates the subscription's activated timestamp and creates an event whose type is subscription.extended.

You should use subscription.extended as a trigger to notify customers that the trial has been converted into a paid subscription.

If payment capture fails, then the invoice becomes uncollectible and the subscription moves into a failed state. To learn more, refer to Handling failed renewals.

Ending trial subscriptions

To avoid getting charged, customers may opt to cancel their subscription during its trial period. In these cases, you have two options:

Extending free trial periods

Sometimes you might want to extend a customer's free trial period or keep customers at a no-charge level indefinitely. To do this, after you activate the subscription, do not update its price. By not performing this operation, a subscription's items[] will have a price or aggregatePrice of 0.0on the nextInvoiceDate, and, as a result, Digital River doesn't make any invoice collection attempts, and the subscription's state remains activeFree.

Reverting to a free subscription

You can also push an active subscription back into an activeFree state. This is useful if you offer various subscription pricing tiers and customers request that their access be downgraded to the basic, free level.

To do this, send a POST /subscriptions/{id} request that updates the price or aggregatePrice of each of the subscription's items[] to 0.0 and the planId to an appropriate plan. On the nextInvoiceDate, the subscription's state reverts to activeFree.

Modifying subscription payments

For more details on how subscriptions can be modified, refer to Updating subscriptions.

When customers want to manage their subscriptions, you can retrieve a list of subscriptions associated with their record:

curl --location --request GET 'https://api.digitalriver.com/subscriptions?customerId=f9acfc5b-42de-4807-8248-eb1cb8069a04' \
--header 'Authorization: Bearer <Secret API key>' \
...

For each subscription, access its payment source by passing sourceId in a GET /sources/{sourceId} request.

To modify a subscription's payment source, its state must be active, activeFree, or activePendingInvoice. If this precondition is met, you can:

Update credit card information

If a subscription's sourceId references a source with a type of creditCard, then you can provide customers the ability to update that card's billing information or expiration date.

{
    "id": "f9f73fd2-b56d-40d2-92fe-de4987671c34",
    ...
    "sourceId": "26ab35a7-64f7-4cf5-82e6-18cc444cd993",
    ...
    "state": "activeFree",
    ...
}

If you want to display the card's current billing information and card information to customers, you can retrieve that data from the source's owner and creditCard blocks.

Billing address information

If customers opt to edit their billing information, present them with a form to enter the full name, email, and address (line 1, line 2, city, state, country, postal code) associated with the credit card.

Card expiration date

If customers opt to edit their credit card's expiration date, use a cardexpiration element to provide them with an input field.

Configuring the update source method

Once customers enter and save their changes, pass the submitted data to updateSource(). Make sure you configure the appropriate version of the method, depending on whether customers submit updated (a) billing address information, (b) card expiration information, or (c) both. In both versions, you need to add the source's id and clientSecret to the method's configuration object.

Replace an existing source with a new source

When customers want to change how they pay for a subscription, you can allow them to supply a new payment method.

How you replace a subscription's current source with a new source depends on whether you're using Drop-in payments or DigitalRiver.js with Elements.

In both cases, first collect and store the customer's billing information.

Build the createDropin() method's configuration object:

let digitalriverpayments = new DigitalRiver("pk_hc_a209389e4588433bb6e00b32466b82c3", {
    "locale": "en_GB"
});
                        
let configuration = {
    "options": {
        "flow": "managePaymentMethods",
        "showComplianceSection": true,
        "showTermsOfSaleDisclosure": true,
        "usage": "subscription"
    },
    "billingAddress": {
        "firstName": "John",
        "lastName": "Doe",
        "email": "test@test.com",
        "phoneNumber": "952-253-1234",
        "address": {
            "line1": "16 Byward St",
            "city": "London",
            "state": "England",
            "postalCode": "EC3R 5BA",
            "country": "GB"
        }
    },
    ...
}
                                    
let dropin = digitalriverpayments.createDropin(configuration);
dropin.mount("drop-in-container");

Pass the configuration object to createDropin(). If the request is successful, the onReady event contains the transaction's eligible payment methods:

{
    "paymentMethodTypes": [
        "creditCard",
        "payPalBilling"
    ]
}

Each payment method and its disclosures are displayed in the window. If customers click the button without accepting these agreements and terms, Drop-in blocks the transaction from proceeding.

If customers accept the terms, submit their information, and the resulting create source request is successful, the onSuccess event contains a source that is readyForStorage and chargeable.

For more details, refer to the Drop-in payments integration guide and the Drop-in payments builder tool.

Send the source, customer, and subscription identifiers to your backend.

Use a POST /customers/{customerId}/sources/{sourceId} to attach the source to the customer. This flips the source's reusable attribute to true.

To update the subscription, send its identifier as a path parameter in a POST /subscriptions/{subscriptionId}. In the body of the request, specify the new sourceId.

curl --location --request POST 'https://api.digitalriver.com/subscriptions/b8dc06d6-941e-483c-89a1-263874bff3b4' \
...
--data-raw '{
	"sourceId": "e4adbcac-1551-4743-9a3e-48dc3883241b"
} 

If you receive a 200 OK, notify customers that their subscription's designated payment method has been successfully updated.

Replace an existing source with a saved source

When customers want to change how they pay for a subscription, you can give them the option of selecting one of their saved payment sources.

To access these sources, send the customer's identifier in a GET /customers/{customerId} request. From the response, you can retrieve any of the sources[], since, by default, they're all chargeable and reusable.

{
    "id": "533319260336",
    "createdTime": "2021-05-06T21:51:08Z",
    "email": "jackdoe@digitalriver.com",
    "shipping": {
        "address": {
            "line1": "123 Boulevard",
            "city": "Saint Paul",
            "postalCode": "55155",
            "state": "MN",
            "country": "US"
        },
        "name": "John Doe",
        "phone": "555-555-5555"
    },
    "defaultSourceId": "5e359d60-1d23-4234-84ee-e1c9b3ed7edc",
    "sources": [
        {
            "id": "19f47eba-418f-41b3-882c-462e335770e7",
            "createdTime": "2022-03-30T21:14:05Z",
            "type": "payPalBilling",
            "currency": "USD",
            "amount": 27.01,
            "reusable": true,
            "state": "chargeable",
            "owner": {
                "firstName": "Maya",
                "lastName": "Brown",
                "email": "null@digitalriver.com",
                "address": {
                    "line1": "10381 Bren Rd W",
                    "city": "Minnetonka",
                    "postalCode": "55343",
                    "state": "MN",
                    "country": "US"
                }
            },
            "paymentSessionId": "46206596-6559-4f86-9f27-2ccb4d0cc677",
            "clientSecret": "19f47eba-418f-41b3-882c-462e335770e7_cc871d23-474d-4a3f-9803-4e98fa39f2ee",
            "payPalBilling": {
                "token": "12345",
                "payerId": "payerId",
                "payerStatus": "verified",
                "redirectUrl": "https://api.digitalriver.com:443/payments/redirects/b9cd5136-8da3-4e00-97af-8b5fe4b70fdf?apiKey=pk_test_da4311e7b7384b7caf5384fb79808192",
                "returnUrl": "http://mypage.com",
                "offline": false
            }
        },
        {
            "id": "1e80940d-33d2-43d8-89c1-09c8076b2654",
            "createdTime": "2021-05-19T19:35:47Z",
            "type": "creditCard",
            "reusable": true,
            "state": "chargeable",
            "owner": {
                "firstName": "William",
                "lastName": "Brown",
                "email": "null@digitalriver.com",
                "address": {
                    "line1": "10381 Bren Rd W",
                    "city": "Minnetonka",
                    "postalCode": "55343",
                    "state": "MN",
                    "country": "US"
                }
            },
            "clientSecret": "1e80940d-33d2-43d8-89c1-09c8076b2654_3ada8e16-3938-4495-af72-5f793ff649c8",
            "creditCard": {
                "brand": "Visa",
                "expirationMonth": 7,
                "expirationYear": 2027,
                "lastFourDigits": "1111"
            }
        },
        ...
}

Use a selection control to display these saved sources to customers. With credit cards, you can retrieve brand, expirationMonth, expirationYear, and lastFourDigits and display this information to customers so they are able to identify the card. If the customer opts to use a saved source, retrieve its unique identifier.

To update the subscription, send its identifier as a path parameter in a POST/ subscriptions/{subscriptionId} and, in the request body, specify the selected sourceId.

curl --location --request POST 'https://api.digitalriver.com/subscriptions/b8dc06d6-941e-483c-89a1-263874bff3b4' \
...
--data-raw '{
	"sourceId": "e4adbcac-1551-4743-9a3e-48dc3883241b"
} 

If you receive a 200 OK, notify customers that their subscription's designated payment method has been successfully updated.

Cancelling subscriptions

When you either (1) receive a request from the customer to cancel a subscription, and the request adheres to the terms of the agreement (or you grant the customer a waiver), or (2) you decide to cancel the subscription, send aPOST /subscriptions/{subscriptionId} with state set to cancelled in the request's payload.

curl --location --request POST 'https://api.digitalriver.com/subscriptions/895554f1-0568-4387-8405-551ddb533ff8' \
...
--data-raw '{
        "state": "cancelled"
}'

No other values can be passed in the body of a cancellation request. If you attempt to do so, the following error is returned:

{
    "type": "conflict",
    "errors": [
        {
            "code": "restricted_update",
            "parameter": "metadata",
            "message": "Additional data cannot be updated when updating state to cancelled."
        }
    ]
}

Only active , activeFree, and activePendingInvoice subscriptions can be cancelled. When you cancel an activePendingInvoice subscription, the underlying open invoice is moved into a void state.

A successful cancellation request returns a 200 OK, moves the subscription into a cancelled state and prevents billing from occurring on the nextInvoiceDate.

On your site's subscription management page, include a cancellation button that, when clicked, sends this cancellation request to Digital River. When you receive a successful response, send the customer a subscription cancellation confirmation email and indicate that no future billing will occur.

Deleting subscriptions

To delete a draft subscription, retrieve its unique identifier, and pass it as a path parameter in a DELETE /subscriptions/{id} request.

A successful request results in the creation of an event with a type of subscription.deleted.

Only subscriptions whose state is draft can be deleted. If you attempt to delete a non-draft subscription, then the following error is thrown:

409 Conflict
{
    "type": "conflict",
    "errors": [
        {
            "code": "invalid_state",
            "parameter": "state",
            "message": "Subscription c090749a-8f8f-43a5-8e9c-9b434a710b1c is active, so it cannot be deleted."
        }
    ]
}Java

If you want to stop recurring payments on an activated subscription, you can either cancel the subscription or deactivate its plan.

Deactivating a plan terminates all subscriptions that belong to that plan.

Updating plans

Updating a plan changes the behavior of all the subscriptions it controls. As a result, we generally recommend only using the POST /plans/{planId} operation to optimize or phase it out.

For details on how changing a plan's state affects a subscription, refer to Lifecycle of a plan.

Ending subscription reminders

To stop renewal reminders from getting generated on a subscription, you need to update its plan by assigning a negative integer to reminderOffSetDays.

curl --location 'https://api.digitalriver.com/plans/490bf585-26e0-4413-9263-ed68af3a6cc3' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <Secret API key>' \
...
--data '{
  "reminderOffsetDays": -1
}'

When a subscription on that plan moves into its next billing period, Digital River deletes its nextReminderDate. As a result, the event with a type of subscription.reminder does not get created.

If you make this update to a plan's reminderOffSetDays, then the billing behavior of all of its subscriptions remains unchanged.

Updating subscriptions

A POST /subscriptions/{subscriptionId} request allows you to both activate a subscription and cancel a subscription as well as make updates to any of its following attributes:

A successful request results in the creation of an event with a type of subscription.updated.

For details on how to handle subscription updates in free trials, refer to updating the subscription's price and plan in the Trial management section.

To successfully update a subscription, its state must be draft, active, activeFree, or activePendingInvoice.

When Digital River opens an invoice on nextInvoiceDate, we move the subscription's state to activePendingInvoice and implement a blackout period. As a result, any updates you make to the subscription during this period won't take effect until the next billing cycle.

Therefore, performing a GET /subscriptions or GET /subscriptions/{id} can't be used to identify a subscription's current state. Instead, these requests return the scheduled settings for the next renewal.

In most cases, if you make a subscription update, we recommend that you notify customers (typically by email) of the change. In the email, include a link to the customer's subscription management page, and on that same page, make sure you install a cancellation button that, when clicked, sends a subscription cancellation request to Digital River.

Associated plan

If you want to modify the timing of a subscription's renewal reminder event, when billing is initiated, or the length of the payment collection period, you must associate the subscription with a different planId. If you move an active subscription to a different plan, the new settings are applied to future billing periods.

Always acquire the customer's consent before changing a subscription's billing frequency. In most cases, we recommend you create a new subscription. Since billing frequency is defined by a plan's interval and intervalCount, and these attributes can't be modified in a POST /plans/{planId}, you'd need to associate the subscription with a different plan, which can potentially cause issues.

For example, you might have a subscription that's on an annually renewing plan. If you use a POST /subscriptions/{subscriptionId} to associate the subscription with a different, monthly-billing plan, then the subscription will remain on its current, annual plan until the end of the contract binding period. Not until that point will the subscription switch to the monthly plan.

Associated payment source

For details, refer to the Modifying subscription payments section.

SKUs and product details

In an update subscription request, you can either pass items[].skuId or items[].productDetails.

For details, refer to Managing SKUs or Using product details.

A common use case for this operation is when upgrading or downgrading a customer's subscription service. For example, customers might want to migrate from basic to professional offerings.

Price

Digital River's standardized autorenewal terms allow you to make price or aggregatePrice changes to any of a subscription's line items. You must, however, provide customers advance notification (typically by email) of the change, along with instructions on how to cancel the subscription if they don't agree to the price increase.

Quantity

For each of a subscription's items[] , the default quantity is 1. So, unless you specify quantity when updating a line item in a subscription, its value is automatically set to 1 .

Any updates to quantity typically require the customer's consent.

Handling chargebacks

When any of your webhook endpoints receive an event whose type is order.chargeback, parse its payload to determine whether the order contains a subscriptionId. You should cancel the subscription to avoid further chargebacks and fees if it does.

Last updated