Subscriptions

Scheduled payments

Subscriptions helps you establish a recurring revenue stream and offer updated content or premium experiences for a fee on a weekly or monthly basis. The subscriptions feature allows you to set prices based on local currency (ex: Japanese yen, British pound and so on) and offer different levels of subscriptions. Additionally, you can choose whether to offer a free trial and for how long.

Overview

Subscriptions are a great way to retain and engage players. Games can structure their subscription offer to reward people on a daily basis for coming to the game.

The subscriptions dialog

Payment and Billing

Subscriptions are pre-paid and the player has to pay at the beginning of the pay cycle. When a payment is due on a subscription, we update the subscription object's values for the next bill time and current period start-time, reflecting the passage of a subscription period. We then attempt to process the payment in a smart queue that manages retries.

A sample Subscription implementation

Developers can find out when there has been a chargeback by either querying for the payment objects for each user at regular intervals or by registering a webhooks update for the payment object.

When a player’s payment for a subscription fails Facebook will attempt several automated retries to collect funds from the existing funding source. In addition to retries, we'll also notify the player of the failed payment, and provide them the opportunity to repay for the subscription with a new funding source.

There are 4 payment failure scenarios, all of which apply to both credit card and PayPal:

  • Situations where we deem the payment instrument to be "non-chargeable" ex. Blacklisted card => we disable the payment instrument and don't retry.
  • Situations where we deem the payment instrument to be "chargeable" ex. Reason codes like Insufficient funds (NSF), Credit Limit Hit => retry every 24 hours, up to a maximum of 3 times
  • Other, Facebook internal errors (ex. database error, system unavailable) => retry every 6 hours, for up to a maximum of 4 times
  • Other, payment provider-side errors (ex. PayPal unavailable) => retry every 12 hours, for up to a maximum of 4 times

An app can define multiple subscriptions associated with the app. However, a player can have only one active subscription at any time for that app (doesn't apply to test users and users listed as Payments Testers, who can purchase multiple subscriptions for the same app).

If a user with an active subscription uninstalls the app, then the subscription will be put into the pending_cancel state, and will be terminated at the end of the billing cycle. This way, if a player re-installs the app, the developer can choose to prompt them to re-activate via the client-side flow.

If a user with an active subscription deletes their Facebook account, their subscription will be canceled immediately.

A failed payment doesn't immediately affect the subscription. In fact, the subscription will remain active for the remainder of the billing cycle, unless you, the developer, explicitly cancel it.

Defining a subscription object for your application

A subscription object is an fbpayment:subscription Open Graph object that describes the details of a subscription offered by your application. Details about how Open Graph works can be found in our OG object documentation. An fbpayment:subscription object requires the following metadata tags:

tag description

og:title

The title for your subscription

og:image

A image that Facebook can associate with your subscription

og:description

The description of your subscription

og:type

The object type, which for subscriptions is always “fbpayment:subscription”

fb:app_id

The application id that this subscription will be used in.

fbpayment:price

The monthly price for this subscription, specified as a string consisting of a numeric price and an ISO-3 currency code, separated by a space, in either order

fbpayment:alternate_price

(optional, multiple allowed) Similar to price; this allows for pricing in extra currencies

fbpayment:trial_duration

(optional) The amount of time (in days, weeks or months) that a player can use this subscription before the first billing period will begin

fbpayment:billing_period

(optional) How frequently we charge for the subscription in weeks or months. Valid values include 1 week or 2 months. The default is 1 month.

Example:

<html>
    <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# fbpayment: http://ogp.me/ns/fb/fbpayment#">   
        <meta property="og:type" content="fbpayment:subscription" />    
        <meta property="og:title" content="Abhi's Bronze Subscription" />
        <meta property="og:image" content="https://s-static.ak.fbcdn.net/images/devsite/attachment_blank.png" />
        <meta property="og:description" content="The Best bronze subscription around!" />
        <meta property="fbpayment:price" content="5.99 USD" />
        <meta property="fbpayment:alternate_price" content="3.99 EUR" />
        <meta property="fbpayment:alternate_price" content="3.99 GBP" />
        <meta property="fbpayment:trial_duration" content="7 days" />
        <meta property="fbpayment:billing_period" content="1 week" />
        <meta property="fb:app_id" content="214417841952278" />
        <meta property="og:url" content="http://samples.ogp.me/231899796870749" />
        ...

Notes

  • There may be zero or more alternate_price properties, to allow the application to price subscriptions differently for different currencies.
  • For users whose preferred currencies aren't explicitly listed among the subscription object's price/alternate_price properties, Facebook will determine a price based on the price at our exchange rates, which are updated daily.
  • Developers can supply a trial_duration which allows the user to get a free trial for the specified period. A given player can enjoy a free trial for a particular application, for any subscription, only once.
  • If a price field is malformed (ex. 'US$ 5.00', rather than the correctly formed '5.00 USD'), Facebook can't catch it until a transaction is attempted. If, in your testing, you get a "null" value passed to your client-side callback, it may be for this reason.

Prompting a User to Purchase a Subscription

Once an application has created at least one subscription Open Graph object, prompting a player to purchase a subscription requires using the Facebook Pay Dialog. The following snippet can be used to start a subscription purchase dialog:

var obj = {
    method: 'pay',
    action: 'create_subscription',
    product: 'URL_TO_SUBSCRIPTION_OBJECT'
  };
FB.ui(obj, js_callback);

Where product must be the url that hosts the subscription's open-graph object.

Subscriptions dialog

On completion or cancelation of the subscription purchase dialog, the Javascript callback will be called. If there's success, the callback's argument will be an object containing the keys:

  • subscription_id: the unique identifier that represents the user’s active subscription
  • status: “active”
Subscription confirmation

Prompting a User to Modify the Payment Method for a Subscription

Once a player has already purchased a subscription, it's possible for the application to prompt them to change the payment method currently being used to pay for the service. For example, a user who has an expired credit card on file can update the payment method from within the application with this functionality.

This subscription modification dialog can be invoked with the following snippet:

var obj = {
     method: 'pay',
     action: 'modify_subscription',
     subscription_id: USER_SUBSCRIPTION_ID,
  };
FB.ui(obj, callback);

Where subscription_id must be the unique identifier that represents the player’s subscription.

Change payment method dialog

On success, Facebook will invoke the specified callback with an object containing:

  • subscription_id: this is the same subscription_id that was provided when invoking this API
  • status: “active” – indicates that the modified subscription is active.

In the case where the player cancels the subscription modification dialog, or if there's an error, the object will instead contain an error code and message.

Prompting a User to Upgrade/Downgrade a Subscription

Once a player already has purchased a subscription, the application can prompt to change the subscription. For example, a player may want to upgrade from a “Bronze” subscription to a “Silver” one or downgrade from a “Silver” subscription to a “Bronze” one.

Subscription upgrades (defined as ones costing the same as, or more than, the existing subscription) take effect immediately and the user is charged a pro-rated amount for the rest of the current billing cycle. Subscription downgrades (costing less than the existing subscription) take effect at the start of the subsequent billing cycle.

var obj = {
     method: 'pay',
     action: 'change_subscription',
     subscription_id: USER_SUBSCRIPTION_ID,
     product: 'URL_TO_SUBSCRIPTION_ WEBPAGE'
  };
FB.ui(obj, callback);

Parameters:

  • subscription_id: user-subscription unique identifier returned when the player purchased this subscription
  • product: URL of the application’s subscription open graph object that the player is switching to

As above, on success, Facebook will invoke the callback method with an object containing these keys:

  • subscription_id: the unique identifier that represents the player’s subscription. (Note that the same subscription_id as was provided when invoking this API)
  • status: “active” – indicates that the changed subscription is active. For upgrades, it means that the player is now subscribed to the service determined by the provided product parameter. For downgrades, this means that the player’s subscription will change to the service determined by the provided product parameter at the start of the subsequent billing cycle.

Prompting a User to Cancel a Subscription

You may use this functionality to allow a subscriber to cancel his or her existing subscription. After a player takes the action to cancel a subscription, it'll be in the “pending cancelation” state and will actually be canceled at the end of the current billing cycle. This means that the player must continue to receive all the benefits from the subscription until then. Also, note that a player can reactivate a subscription that is in a “pending cancelation” state, as described below.

This subscription cancel dialog can be invoked with the following js snippet:

var obj = {
    method: 'pay',
    action: 'cancel_subscription',
    subscription_id: USER_SUBSCRIPTION_ID
  };
FB.ui(obj, js_callback);
Cancel Subscription Dialog

On success, the callback will be passed an object containing the following parameters:

  • subscription_id: the unique identifier that represents the player’s subscription
  • status: “active” – as described above, cancelation doesn't happen immediately, indicating that the player’s subscription is still active, but has decided to cancel their subscription. The change will take effect at the end of the current billing cycle.
Cancel Subscription Dialog

Prompting a User to Reactivate a Subscription

Once a player has decided to cancel a subscription, but before the cancelation actually takes place, a developer can re-engage the user via the reactivation flow. Note that if the cancelation is initiated by the app, this reactivation flow won't work.

After a player cancels a subscription, it will be placed in a “pending cancelation” state. Before the end of the current billing cycle, the player can reactivate the subscription and it will become active again. (The next charge will occur at the start of the next billing cycle.)

Reactivation Dialog

var obj = {
    method: 'pay',
    action: 'reactivate_subscription',
    subscription_id: USER_SUBSCRIPTION_ID
  };
FB.ui(obj, js_callback);
  • subscription_id: user-subscription unique identifier returned when the player purchased this subscription
Cancel Subscription Dialog

On success, the callback will be passed an object containing the following parameters:

  • subscription_id: the unique identifier that represents the player’s subscription
  • status: “active” – Indicates that the player has reactivated the subscription

Prompting a user to settle after payment failure

If a payment can't be processed to fund a player's subscription, the payment_status flag on the subscription object will be false. In that case, the app can request the player to settle that payment using the pay dialog as illustrated in this snippet:

var obj = {
     method: 'pay',
     action: 'settle_subscription',
     subscription_id: USER_SUBSCRIPTION_ID,
  };
FB.ui(obj, js_callback);
  • subscription_id: the user-specific subscription ID number

On success, the callback will be passed an object containing the following parameters:

  • subscription_id: the unique identifier that represents the player’s subscription
  • status: active to indicate that the player has reactivated the subscription

In the case where the player cancels of the dialog, or on an error, the object will contain an error code and message. If the subscription is already settled (ex. the subscription object's payment_status is success) when the dialog is invoked, the player will see an error. It's the application's responsibility to verify the player's settlement status before proceeding.

Querying for a User’s Subscriptions

Developers can use the Graph API /USER_ID/payment.subscriptions endpoint with an app access_token to access a player's subscriptions associated with that application. By default, only active subscriptions will be returned. You can pass a status=canceled parameter if you also want canceled subscriptions.

GET https://graph.facebook.com/USER_ID/payment.subscriptions

Sample Response

{
  1234: {
  id: 1234,
  user: {
      "name": "Bikash Agarwalla",
      "id": "1245537185"
  },
  application: {
      "name": "Application",
      "id": "10245213"
  },
  status: "active",
  created_time: "2012-03-16T20:10:34+0000",
  updated_time: "2012-03-16T20:10:34+0000",
  amount: "10.00",
  currency: "USD",
  product: "http://current_item",
  period_start_time: "2012-03-16T20:10:34+0000",
  next_bill_time: "2012-04-16T20:10:34+0000",
  next_period_product: "http://next_item",
  next_period_amount:: "20.00",
  next_period_currency: "USD",
  billing_period: "1 month",
  payment_status: "success", 
  last_payment: {
    "id": 3566,
    "actions": [
      {
        "type": "charge",
        "status": "completed",
        "amount": "10.00",  
        "currency": "USD",
        "time_created": "2012-03-16T20:10:34+0000",
        "time_updated": "2012-03-16T20:10:34+0000",
    },
    "refundable_amount": {
        "currency": "USD",
        "amount": "10.00"
    },
    "country": "US",  
  }
}

Querying for the Details of a Specific Subscription

Calling the Graph API /SUBSCRIPTION_ID/ endpoint with an app access_token returns details about a specific subscription, as long as it belongs to the application.

GET https://graph.facebook.com/SUBSCRIPTION_ID/

Response Values

  • id: the ID of the subscription
  • user: array containing user who is subscribed (name, id)
  • application: array containing application info (name, id)
  • status: status of the subscription [active, canceled]
  • product: the url that defines the subscription's open-graph object for the user in the current billing cycle
  • amount: the amount the user is subscribed for in the current billing period
  • currency: ISO-3 currency code for the current period amount.
  • period_start_time: date that the current billing cycle began
  • created_time: date on which subscription was created
  • updated_time: date on which subscription was last updated
  • next_period_product: the url that defines the subscription's open-graph object for the user in the next billing cycle
  • next_period_amount: the amount that the player will pay in the next billing period
  • next_period_currency: ISO-3 currency code for the next period amount.
  • billing_period: how often we bill the users. Formatted like '1 month'. The valid periods are 'month' and 'week'.
  • next_bill_time: date that the next billing cycle will begin
  • trial_expiry_time: date on which any promotion (if provided) expires or expired for this subscription
  • trial_amount: amount that applies during promotion period
  • trial_currency: ISO-3 currency code corresponding to promotion amount
  • pending_cancel: Boolean indicating whether the player has decided to cancel the subscription at the end of the current billing cycle. (NOTE: this will only be true when a player has taken explicit action to cancel the subscription. In other words, a subscription for which a payment has failed won't have this flag set to true.)
  • canceled_reason: flag indicating why a subscription has been canceled [user_decision, app_decision, failed_payment, none]
  • payment_status: string indicating the status of the payment for the current billing cycle [success, failed, not_billed]. It'll be "success" if last payment for the player succeeded. It'll be "failed" if last payment for the player failed. If the player hasn't been billed (for example, if it is in free trial), this will be set to "not_billed".
  • last_payment: details for the last payment, an object with fields 'id', 'actions', 'refundable_amount' and 'country'

Sample Response

  • In this example, we have a user who signed up for a 9.99 USD “gold” subscription service on 03/01/2012 and received a 2-week free trial. Sometime after 04/14/2012 and before 05/14/2012, the player decided to downgrade to the “bronze” subscription that costs only 5.99 USD. Assume that the current date is 05/03/2016.
{
  id: "122119087921267",
  user: {
      "name": "Bikash Agarwalla",
      "id": "1245537185"
 },
 application: {
      "name": "Application",
      "id": "10245213"
 },
 status: "active",
 created_time: "2012-04-01",
 updated_time: "2012-04-17",
 amount: "9.99",
 currency: "USD",
 product: "www.application.com/gold_subscription.html",
 period_start_time: "2012-04-14",
 next_bill_time: "2012-05-14",
 next_period_product: "www.application.com/bronze_subscription.html",
 next_period_amount:: "5.99",
 next_period_currency: "USD",
 billing_period: "1 month",
 trial_amount: "0",
 trial_currency: "USD",
 trial_expiry_time: "2012-04-14",
 payment_status: "success",
 last_payment: {
    "id": 3566,
    "actions": [
      {
        "type": "charge",
        "status": "completed",
        "amount": "9.99",  
        "currency: "USD",
        "time_created": "2012-04-14T20:00:00+0000",
        "time_updated": "2012-04-14T20:00:00+0000",
    },
    "refundable_amount": {
        "currency": "USD",
        "amount": "9.99"
    },
    "country": "US",  
  }
}

Additional example response

{id: "122119087921265",
 user: {
      "name": "Bikash Agarwalla",
      "id": "1245537185"
 },
 application: {
      "name": "Application",
      "id": "10245213"
 },
 status: "active",
 created_time: "2012-04-16T20:10:34+0000",
 updated_time: "2012-04-17T20:10:34+0000",
 amount: "10.00",
 currency: "USD",
 product: "http://current_item",
 period_start_time: "2012-04-16T20:10:34+0000",
 next_bill_time: "2012-05-17T20:10:34+0000",
 next_period_product: "http://next_item",
 next_period_amount:: "20.00",
 next_period_currency: "USD",
 billing_period: "1 month",
 trial_amount: "0",
 trial_currency: "USD",
 trial_expiry_time: "2012-04-17T20:10:34+0000",
 pending_cancel: true,
 canceled_reason: "user_decision",
 payment_status: "not_billed"}

Updating a Specific Subscription

Certain properties of a subscription can be updated by the application.

  • You can choose to push out the next billing date in case they wish to give players free usage time, most often as a compensation for poor delivery of service or other dissatisfaction.
  • You can choose to discount the subscription for a given user, by updating the price of the subscription for that user to a value lower than the user's current price. An app might do this to avoid punishing early adopters if it later lowers the price of a subscription.
  • You can cancel the subscription for a particular user at any time, without their explicit consent. You can choose to do so either immediately or at the end of a billing cycle.

The subscription's billing-period can't be modified once the subscription is active. If you need to modify it, you must cancel the active subscription and prompt the user to create a new one.

To do any of these things, invoke the Graph API /SUBSCRIPTION_ID/ endpoint with an app access_token and the appropriate parameters from the list below.

POST https://graph.facebook.com/SUBSCRIPTION_ID/

Parameters

  • next_bill_time (optional): string timestamp for when the next billing date should be (i.e 2013-01-11T10:40:40+0000)
  • amount (optional): string that includes the amount (i.e 5.99) - note that without explicit user consent, theamount must be lower, denominated in the same currency, than the amount specified by the player's existing billing agreement
  • currency (optional - required if amount is specified): ISO-3 currency code (ex. USD)
  • status (optional): the status that the subscription is in (the application can cancel a subscription)
  • canceled indicates that the subscription should be canceled.
  • cancel_type (optional) parameter with values either:
  • immediate (default) indicates that the subscription should be canceled now.
  • pending indicates that the subscription should be canceled at the end of current billing cycle.

Query for the details of any Payment

Developers can also use the Graph API /PAYMENT_ID/ endpoint with an app access token to get the details of a specific subscription payment.

GET https://graph.facebook.com/PAYMENT_ID/

Example Response

{
  "payment_id": 90010000008188,
  "user": {
    "name": "Bikash Agarwalla",
    "id": "1245537185"
  },
  "application": {
    "name": "FBCredits Demo",
    "namespace": "credits_demo",
    "id": 81947918671,
  },
  "actions": [
    {
      "type": "charge",
      "status": "completed",
      "amount": "1.00",  
      "currency": "USD",
      "time_created": "2012-04-16T20:10:34+0000",
      "time_updated": "2012-04-16T20:10:34+0000",
    },
    {
      "type": "refund",
      "status": "completed",
      "amount": "0.20",
      "currency": "USD",
      "time_created": "2012-04-18T10:10:34+0000",
      "time_updated": "2012-04-18T10:10:34+0000",
    },
    {
      "type": "refund",
      "status": "processing",
      "amount": "0.30",
      "currency": "USD",
      "time_created": "2012-04-20T10:10:34+0000",
      "time_updated": "2012-04-20T10:10:34+0000",
    },
  ],
  "refundable_amount": {
    "amount": "0.50",
    "currency": "USD",
  }

  "items": [{
    "type": "SUBSCRIPTION",
    "id": 376537519748,
    "product": "http://test.com/test_subscription",
    "period_start_time": "2012-03-16T10:10:34+0000",
    "period_end_time" : "2012-04-16T10:10:34+0000",
    "amount": "10.10"
    "currency": "USD"
  }],
  "request_id": "12345",
  "country": "US",   
}