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. |
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.
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.
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:
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.
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 |
---|---|
| The title for your subscription |
| A image that Facebook can associate with your subscription |
| The description of your subscription |
| The object type, which for subscriptions is always “fbpayment:subscription” |
| The application id that this subscription will be used in. |
| 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 |
| (optional, multiple allowed) Similar to |
| (optional) The amount of time (in days, weeks or months) that a player can use this subscription before the first billing period will begin |
| (optional) How frequently we charge for the subscription in weeks or months. Valid values include |
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" /> ...
alternate_price
properties, to allow the application to price subscriptions differently for different currencies.price
/alternate_price
properties, Facebook will determine a price based on the price
at our exchange rates, which are updated daily.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.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.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.
The subscription creation call does not support custom request_id
parameters, even if you specify it. Every payment created by the subscription will contain an auto-generated request_id
.
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 subscriptionstatus
: “active”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.
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 APIstatus
: “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.
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 subscriptionproduct
: URL of the application’s subscription open graph object that the player is switching toAs 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.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);
On success, the callback will be passed an object containing the following parameters:
subscription_id
: the unique identifier that represents the player’s subscriptionstatus
: “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.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.)
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 subscriptionOn success, the callback will be passed an object containing the following parameters:
subscription_id
: the unique identifier that represents the player’s subscriptionstatus
: “active” – Indicates that the player has reactivated the subscriptionIf 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 numberOn success, the callback will be passed an object containing the following parameters:
subscription_id
: the unique identifier that represents the player’s subscriptionstatus
: active
to indicate that the player has reactivated the subscriptionIn 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.
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
{ 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", } }
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/
id
: the ID of the subscriptionuser
: 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 cycleamount
: the amount the user is subscribed for in the current billing periodcurrency
: ISO-3 currency code for the current period amount.period_start_time
: date that the current billing cycle begancreated_time
: date on which subscription was createdupdated_time
: date on which subscription was last updatednext_period_product
: the url that defines the subscription's open-graph object for the user in the next billing cyclenext_period_amount
: the amount that the player will pay in the next billing periodnext_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 begintrial_expiry_time
: date on which any promotion (if provided) expires or expired for this subscriptiontrial_amount
: amount that applies during promotion periodtrial_currency
: ISO-3 currency code corresponding to promotion amountpending_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'{ 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", } }
{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"}
Certain properties of a subscription can be updated by the application.
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/
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 agreementcurrency
(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.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/
{ "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", //request_id is auto-generated for subscription payments "country": "US", }