API: Subscriptions

URI/Method

Resource/URI GET POST PUT DELETE
Subscriptions
/subscriptions
List subscriptions Create new subscription
Subscription
/subscriptions/<x>
Read subscription Update subscription Cancel subscription

Subscription Input Attributes

When creating a subscription, you must specify a product and a customer. Credit card details may be required, depending on the options for the Product being subscribed (see Product Options).

The product may be specified by product_id or by product_handle (API Handle).

An existing customer may be specified by a customer_id (ID within Chargify) or a customer_reference (unique value within your app that you have shared with Chargify via the reference attribute on a customer). A new customer may be created by providing customer_attributes.

  • product_handle The API Handle of the product for which you are creating a subscription. Required, unless a product_id is given instead.
  • product_id The Product ID of the product for which you are creating a subscription. The product ID is not currently published, so we recommend using the API Handle instead.
  • customer_id The ID of an existing customer within Chargify. Required, unless a customer_reference or a set of customer_attributes is given.
  • customer_reference The reference value (provided by your app) of an existing customer within Chargify. Required, unless a customer_id or a set of customer_attributes is given.
  • customer_attributes
    • first_name The first name of the customer. Required when creating a customer via attributes.
    • last_name The last name of the customer. Required when creating a customer via attributes.
    • email The email address of the customer. Required when creating a customer via attributes.
    • organization The organization/company of the customer. Optional.
    • reference A customer “reference”, or unique identifier from your app, stored in Chargify. Can be used so that you may reference your customer’s within Chargify using the same unique value you use in your application. Optional.
    • address (Optional) The customer’s shipping street address (i.e. “123 Main St.”).
    • address_2 (Optional) Second line of the customer’s shipping address i.e. “Apt. 100”
    • city (Optional) The customer’s shipping address city (i.e. “Boston”).
    • state (Optional) The customer’s shipping address state (i.e. “MA”)
    • zip (Optional) The customer’s shipping address zip code (i.e. “12345”).
    • country (Optional) The customer shipping address country, perferably in [ISO 3166-1 alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format (i.e. “US”).
    • phone (Optional) The phone number of the customer.
  • payment_profile_id The Payment Profile ID of an existing card or bank account, which belongs to an existing customer to use for payment for this subscription. If the card, bank account, or customer does not exist already, or if you want to use a new (unstored) card or bank account for the subscription, use payment_profile_attributes instead to create a new payment profile along with the subscription. (This value is available on an existing subscription via the API as credit_card > id or bank_account > id)
  • payment_profile_attributes (this may also be referred to as credit_card_attributes or bank_account_attributes)
    • first_name (Optional) First name on card or bank account. If omitted, the first_name from customer attributes will be used.
    • last_name (Optional) Last name on card or bank account. If omitted, the last_name from customer attributes will be used.
    • full_number The full credit card number (string representation, i.e. “5424000000000015”)
    • expiration_month (Optional when performing a Subscription Import via `vault_token`, required otherwise) The 1- or 2-digit credit card expiration month, as an integer or string, i.e. “5”
    • expiration_year (Optional when performing a Subscription Import via `vault_token`, required otherwise) The 4-digit credit card expiration year, as an integer or string, i.e. “2012”
    • cvv (Optional, may be required by your gateway settings) The 3- or 4-digit Card Verification Value. This value is merely passed through to the payment gateway.
    • billing_address (Optional, may be required by your product configuration or gateway settings) The credit card or bank account billing street address (i.e. “123 Main St.”). This value is merely passed through to the payment gateway.
    • billing_address_2 (Optional) Second line of the customer’s billing address i.e. “Apt. 100”
    • billing_city (Optional, may be required by your product configuration or gateway settings) The credit card or bank account billing address city (i.e. “Boston”). This value is merely passed through to the payment gateway.
    • billing_state (Optional, may be required by your product configuration or gateway settings) The credit card or bank account billing address state (i.e. “MA”). This value is merely passed through to the payment gateway.
    • billing_zip (Optional, may be required by your product configuration or gateway settings) The credit card or bank account billing address zip code (i.e. “12345”). This value is merely passed through to the payment gateway.
    • billing_country (Optional, may be required by your product configuration or gateway settings) The credit card or bank account billing address country, preferably in [ISO 3166-1 alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format (i.e. “US”). This value is merely passed through to the payment gateway. Some gateways require country codes in a specific format. Please check your gateway’s documentation. If creating an ACH subscription, only US is supported at this time.
    • vault_token (Optional, used only for Subscription Import) The “token” provided by your vault storage for an already stored payment profile
    • customer_vault_token (Optional, used only for Subscription Import) (only for Authorize.Net CIM storage) The customerProfileId for the owner of the customerPaymentProfileId provided as the vault_token
    • current_vault (Optional, used only for Subscription Import) The vault that stores the payment profile with the provided vault_token. May be authorizenet, trust_commerce, payment_express, beanstream, braintree1, braintree_blue, paypal, quickpay, eway, samurai, stripe, or wirecard
    • last_four (Optional, used only for Subscription Import) If you have the last 4 digits of the credit card number, you may supply them here so that we may create a masked card number (i.e. ‘XXXX-XXXX-XXXX-1234’) for display in the UI
    • card_type (Optional, used only for Subscription Import) If you know the card type (i.e. Visa, MC, etc) you may supply it here so that we may display the card type in the UI. May be visa, master, discover, american_express, diners_club, jcb, switch, solo, dankort, maestro, forbrugsforeningen, or laser
    • bank_name (Required when creating a subscription with ACH) The name of the bank where the customer’s account resides
    • bank_routing_number (Required when creating a subscription with ACH) The routing number of the bank
    • bank_account_number (Required when creating a subscription with ACH) The customer’s bank account number
    • bank_account_type (Required when creating a subscription with ACH) Either checking or savings
    • bank_account_holder_type (Required when creating a subscription with ACH) Either personal or business
  • cancellation_message (Optional) Can be used when canceling a subscription (via the HTTP DELETE method) to make a note about the reason for cancellation.
  • next_billing_at (Optional) Set this attribute to a future date/time to sync imported subscriptions to your existing renewal schedule. See the notes on “Date/Time Format” below. If you provide a next_billing_at timestamp that is in the future, no trial or initial charges will be applied when you create the subscription. In fact, no payment will be captured at all. The first payment will be captured, according to the prices defined by the product, near the time specified by next_billing_at. If you do not provide a value for next_billing_at, any trial and/or initial charges will be assessed and charged at the time of subscription creation. If the card cannot be successfully charged, the subscription will not be created. See further notes in the section on Importing Subscriptions.
  • vat_number (Optional) Supplying the VAT number allows EU customer’s to opt-out of the Value Added Tax assuming the merchant address and customer billing address are not within the same EU country.
  • coupon_code (Optional) The coupon code of the coupon to apply (See the coupon docs)
  • payment_collection_method (Optional) The type of payment collection to be used in the subscription. May be automatic, or invoice.
  • agreement_terms (Optional but recommended when creating a subscription with ACH) The ACH agreements terms.

Subscription Output Attributes

The following attributes are returned on a subscription read/list operation.

  • activated_at (Read Only) Timestamp for when the subscription began (i.e. when it came out of trial, or when it began in the case of no trial)
  • balance_in_cents Gives the current outstanding subscription balance in the number of cents.
  • cancel_at_end_of_period Whether or not the subscription will (or has) canceled at the end of the period.
  • canceled_at The timestamp of the most recent cancellation
  • cancellation_message Seller-provided reason for, or note about, the cancellation.
  • coupon_code The coupon code of the coupon currently applied to the subscription
  • created_at The creation date for this subscription
  • credit_card Nested credit card attributes, if payment profile is a credit_card
    • billing_address The current billing street address for the card
    • billing_address_2 The current billing street address, second line, for the card
    • billing_city The current billing address city for the card
    • billing_state The current billing address state for the card
    • billing_zip The current billing address zip code for the card
    • billing_country The current billing address country for the card
    • card_type The type of card used (bogus, visa, master, discover, american_express, diners_club, jcb, switch, solo, dankort, maestro, forbrugsforeningen, or laser)
    • current_vault The vault that stores the payment profile with the provided vault_token. May be authorizenet, trust_commerce, payment_express, beanstream, braintree1, braintree_blue, paypal, quickpay, eway, samurai, stripe, or wirecard
    • customer_id The Chargify-assigned id for the customer record to which the card belongs
    • customer_vault_token (only for Authorize.Net CIM storage): the customerProfileId for the owner of the customerPaymentProfileId provided as the vault_token
    • expiration_month An integer representing the expiration month of the card(1 – 12)
    • expiration_year An integer representing the 4-digit expiration year of the card(i.e. ‘2012’)
    • id The Chargify-assigned ID of the stored card. This value can be used as an input to payment_profile_id when creating a subscription, in order to re-use a stored payment profile for the same customer
    • first_name The first name of the card holder
    • last_name The last name of the card holder
    • masked_card_number A string representation of the credit card number with all but the last 4 digits masked with X’s (i.e. ‘XXXX-XXXX-XXXX-1234’)
    • vault_token The “token” provided by your vault storage for an already stored payment profile
  • bank_account Nested bank account attributes, if payment profile is a bank_account
    • bank_account_holder_type Either business or personal
    • bank_account_type Either checking or savings
    • bank_name The bank where the account resides
    • billing_address The current billing street address for the bank account
    • billing_address_2 The current billing street address, second line, for the bank account
    • billing_city The current billing address city for the bank account
    • billing_state The current billing address state for the bank account
    • billing_zip The current billing address zip code for the bank account
    • billing_country The current billing address country for the bank account
    • current_vault The vault that stores the payment profile with the provided vault_token. As of this time, will only be authorizenet
    • customer_id The Chargify-assigned id for the customer record to which the bank account belongs
    • customer_vault_token (only for Authorize.Net CIM storage): the customerProfileId for the owner of the customerPaymentProfileId provided as the vault_token
    • first_name The first name of the bank account holder
    • last_name The last name of the bank account holder
    • id The Chargify-assigned ID of the stored bank account. This value can be used as an input to payment_profile_id when creating a subscription, in order to re-use a stored payment profile for the same customer
    • masked_bank_account_number A string representation of the stored bank account number with all but the last 4 digits marked with X’s (i.e. ‘XXXXXXX1111’)
    • masked_bank_routing_number A string representation of the stored bank routing number with all but the last 4 digits marked with X’s (i.e. ‘XXXXXXX1111’)
    • payment_type Will be bank_account
    • vault_token The “token” provided by your vault storage for an already stored payment profile
  • current_period_started_at Timestamp relating to the start of the current (recurring) period
  • current_period_ends_at Timestamp relating to the end of the current (recurring) period (i.e. when the next regularly scheduled attempted charge will occur)
  • customer For customer attributes, see Customers API
  • delayed_cancel_at Timestamp for when the subscription is currently set to cancel.
  • expires_at Timestamp giving the expiration date of this subscription (if any)
  • id The subscription unique id within Chargify.
  • next_assessment_at Timestamp that indicates when capture of payment will be tried or retried. This value will usually track the current_period_ends_at, but will diverge if a renewal payment fails and must be retried. In that case, the current_period_ends_at will advance to the end of the next period (time doesn’t stop because a payment was missed) but the next_assessment_at will be scheduled for the auto-retry time (i.e. 24 hours in the future, in some cases)
  • payment_collection_method The type of payment collection to be used in the subscription. May be automatic, or invoice.
  • previous_state Only valid for webhook payloads The previous state for webhooks that have indicated a change in state. For normal API calls, this will always be the same as the state (current state)
  • product For product attributes, see Products API
  • product_price_in_cents (Added Nov 5 2013) The recurring amount of the product (and version) currently subscribed. NOTE: this may differ from the current price of the product, if you’ve changed the price of the product but haven’t moved this subscription to a newer version.
  • product_version_number (Added Nov 5 2013) The version of the product currently subscribed. NOTE: we have not exposed versions (yet) elsewhere in the API, but if you change the price of your product the versions will increment and existing subscriptions will remain on prior versions (by default, to support price grandfathering).
  • signup_payment_id The ID of the transaction that generated the revenue
  • signup_revenue The revenue, formatted as a string of decimal separated dollars and cents, from the subscription signup ($50.00 would be formatted as 50.00)
  • state The current state of the subscription. Please see the documentation for Subscription States
  • total_revenue_in_cents Gives the total revenue from the subscription in the number of cents.
  • trial_started_at Timestamp for when the trial period (if any) began
  • trial_ended_at Timestamp for when the trial period (if any) ended
  • updated_at The date of last update for this subscription

Methods

format may be either ‘xml’ or ‘json’.

List

Listing subscriptions is paginated, 20 at a time by default with an allowed max of 200 per page. They are listed most recently created first.

You may control pagination using the page and/or per_page parameters.

URL: https://<subdomain>.chargify.com/subscriptions.<format>
Method: GET
Optional Parameters:
page: an integer value which specifies which page of results to fetch, starting at 1. Fetching successively higher page numbers will return additional results, until there are no more results to return (in which case an empty result set will be returned). Defaults to 1.
per_page: how many records to fetch in each request, defaults to 20. The maximum allowed is 200 – any per_page value over 200 will be changed to 200.
Response: An array of Subscriptions
Usage Examples:
XML example
JSON example

List By Customer

URL: https://<subdomain>.chargify.com/customers/<customer_id>/subscriptions.<format>
Method: GET
Required Parameters, customer_id
Response: An array of Subscriptions
Usage Examples:
XML example
JSON example

Read

URL: https://<subdomain>.chargify.com/subscriptions/<subscription_id>.<format>
Method: GET
Required Parameters: subscription_id
Response: An single Subscription
XML example
JSON example

Create

URL: https://<subdomain>.chargify.com/subscriptions.<format>
Method: POST
Required Parameters: XML or JSON data, as specified by the required attributes
Response: The created subscription
Usage Examples:
XML example
JSON example

Importing Subscriptions

Subscriptions can be “imported” via the API to handle the following scenarios:

  • You already have existing subscriptions with specific renewal dates that you would like to import to Chargify
  • You already have credit cards stored in your provider’s vault and you would like to create subscriptions using those tokens

Before importing, you should have already set up your products to match your offerings. Then, you can create Subscriptions via the API just like you normally would, but using a few special attributes.

The following additions to the subscription input attributes make imports possible.

  • next_billing_at: set this attribute to a future date/time to sync imported subscriptions to your existing renewal schedule. See the notes on “Date/Time Format” below. If you provide a next_billing_at timestamp that is in the future, no trial or initial charges will be applied when you create the subscription. In fact, no payment will be captured at all. The first payment will be captured, according to the prices defined by the product, near the time specified by next_billing_at. If you do not provide a value for next_billing_at, any trial and/or initial charges will be assessed and charged at the time of subscription creation. If the card cannot be successfully charged, the subscription will not be created.
  • payment_profile_attributes
  • vault_token: the “token” provided by your vault storage for an already stored payment profile
  • customer_vault_token (only for Authorize.Net CIM storage): the customerProfileId for the owner of the customerPaymentProfileId provided as the vault_token
  • current_vault: the vault that stores the payment profile with the provided vault_token. May be authorizenet, trust_commerce, payment_express, beanstream, braintree1, braintree_blue (see additional notes on Braintree Blue, below), paypal, quickpay, eway, samurai, stripe, or wirecard
  • last_four (optional): If you have the last 4 digits of the credit card number, you may supply them here so that we may create a masked card number (i.e. ‘XXXX-XXXX-XXXX-1234’) for display in the UI
  • card_type (optional): If you know the card type (i.e. Visa, MC, etc) you may supply it here so that we may display the card type in the UI. May be visa, master, discover, american_express, diners_club, jcb, switch, solo, dankort, maestro, forbrugsforeningen, or laser

Note: payment_profile_attributes is the same thing as credit_card_attributes used elsewhere in the documentation. The two keys are interchangeable, pick one to use but not both. Most new documentation will refer to payment_profile_attributes

Braintree Blue (Braintree v2) Imports

Braintree Blue is Braintree’s newer (version 2) API. For this gateway, please provide the vault_token parameter with the value from Braintree’s “Customer ID” rather than the “Payment Profile Token”. At this time we do not use current_vault_token with the Braintree Blue gateway.

An implication of this is that we only support a single payment profile per Braintree Customer. We may change this in the future to use both the Customer ID (in customer_vault_token) and the Payment Method Token (in vault_token). When we do this, the change will be transparent to users and merchants of this gateway. However, it will change how imports work. So if you have previously done an import in the past and want to re-use the code, please check this section or watch our changelogs to see if this has changed.

Webhooks During Import

If no next_billing_at is provided, webhooks will be fired as normal. If you do set a future next_billing_at, only a subset of the webhooks are fired when the subscription is created. Keep reading for more information.

Successful creation, no next_billing_at provided
  • signup_success
  • payment_success
Unsuccessful creation (card can’t be charged), no next_billing_at provided
  • signup_failure
Successful creation, next_billing_at provided

Webhooks fired at the time of the API call:

  • signup_success
  • billing_date_change

Webhooks fired when @next_billing_at* is reached:

  • renewal_success or renewal_failure
  • payment_success or payment_failure

Date/Time formats

We will attempt to parse any string you send as the value of next_billing_at in to a date or time. For best results, use a known format like described in [“Date and Time Specification” of RFC 2822](http://tools.ietf.org/html/rfc2822#section-3.3) or [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601).

The following are all equivalent and will work as input to next_billing_at:

Aug 06 11:34:00 -0400 2010
Aug 06 11:34 -0400 2010
2010-08-06T11:34:00-04:00
8/6/2010 11:34:00 EDT
8/6/2010 8:34:00 PDT
2010-08-06T15:34:00Z

You may also pass just a date, in which case we will assume the time to be midnight

2010-08-06

Full Example

Here is a sample JSON document that you might POST to https://<subdomain>.chargify.com/subscription.json to import a subscription:


{
  "product_handle":"basic",
  "next_billing_at":"2010-08-29T12:00:00-04:00",
  "customer_attributes":{
    "first_name":"John",
    "last_name":"Doe",
    "email":"john.doe@example.com",
    "reference":"123",
    "organization":"Acme Widgets"
  },
  "payment_profile_attributes":{
    "vault_token":"12345",
    "customer_vault_token":"67890",
    "current_vault":"authorizenet",
    "expiration_year":"2020",
    "expiration_month":"12",
    "card_type":"visa",
    "last_four":"1111"
  }
}

Update

The update action currently allows you to edit the attributes of the customer, payment profile (credit card), or subscribed product (although no proration or reset options are offered at this time).

This is how you would change the card that somebody uses for their subscription. You can also use this method to simply change the expiration date of the card.

You also use this method to change the subscription to a different product by setting a new value for product_handle. Note that no proration or period reset is initiated when you change the product using this method. This method merely changes the product, and the new payment amount is calculated and charged at the normal start of the next period. If you desire prorated upgrades and downgrades instead, please see the docs on upgrades/downgrades.

URL: https://<subdomain>.chargify.com/subscriptions/<subscription_id>.<format>
Method: PUT
Required Parameters: None
Optional Parameters: XML or JSON data with updated values for customer_attributes or credit_card_attributes
Response: The updated subscription
Usage Examples:
XML example
JSON example

Delete/Cancel

The delete action causes the cancellation of a subscription, i.e. it sets the subscription state to canceled.

URL: https://<subdomain>.chargify.com/subscriptions/<subscription_id>.<format>
Method: DELETE
Required Parameters: None
Optional Parameters: XML or JSON data with a cancellation_message note that will be stored with the subscription.
Response: 200 OK on success
Usage Examples:
XML example
JSON example

Delayed Cancel

Chargify offers the ability to cancel a subscription at the end of the current period (as set by its current product. Setting the subscription to cancel at the end of the period sets the cancel_at_end_of_period to true. Note, that you cannot set cancel_at_end_of_period at subscription creation.

URL: https://<subdomain>.chargify.com/subscriptions/<subscription_id>.<format>
Method: PUT
Required Parameters: None
Optional Parameters: XML or JSON data with cancel_at_end_of_period set to true or false.
Response: The updated subscription
Usage Examples:
XML example
JSON example

Reactivate

Chargify offers the ability to reactivate a previously canceled subscription. For details on how reactivation works, and how to reactivate subscriptions through the Admin Interface, see Reactivation

URL: https://<subdomain>.chargify.com/subscriptions/<subscription_id>/reactivate.xml
Method: PUT
Required Parameters: none
Optional Parameters:
include_trial – Boolean, default 0. If 1 is sent the reactivated subscription will include a trial if one is available. If 0 is sent, the trial period will be ignored. This parameter should be sent in a query string, and does not need to be nested inside a subscription object
preserve_balance – Boolean, default ‘0’. If ‘1’ is passed, the existing subscription balance will NOT be cleared/reset before adding the additional reactivation charges.
coupon_code – The coupon code to be applied during reactivation.
Response: The updated subscription

XML example
JSON example

Reset Balance

Chargify offers the ability to easily reset the balance of a subscription to zero. If a subscription has a positive balance, this API call will issue a credit to the subscription for the outstanding balance. This is particularly helpful if you want to reactivate a canceled subscription without charging the customer for their previously owed balance.

URL: https://<subdomain>.chargify.com/subscriptions/<subscription_id>/reset_balance.xml
Method: PUT
Required Parameters: none
Response: The updated subscription

Usage Examples:
XML example
JSON example

Usage Examples

XML List Usage Example


Feature: Chargify Subscriptions List XML API
  In order integrate my app with Chargify
  As a developer
  I want to interact with my subscriptions via the Chargify API

  Background:
    Given I am a valid API user
    And I accept xml responses


  Scenario: Retrieve a customer's subscriptions
    Given I have a customer with these attributes
      | id             | first_name | last_name | email           |
      | [@customer.id] | Joe        | Blow      | joe@example.com |
    And the customer has 2 subscriptions
    When I send a GET request to https://[@subdomain].chargify.com/customers/[@customer.id]/subscriptions.xml
    Then the response status should be "200 OK"
    And the response should be a "subscriptions" array with 2 "subscription" elements

JSON List Usage Example


Feature: Chargify Subscriptions List JSON API
  In order integrate my app with Chargify
  As a developer
  I want to interact with my subscriptions via the Chargify API

  Background:
    Given I am a valid API user
    And I accept json responses


  Scenario: Retrieve a customer's subscriptions
    Given I have a customer with these attributes
      | id             | first_name | last_name | email           |
      | [@customer.id] | Joe        | Blow      | joe@example.com |
    And the customer has 2 subscriptions
    When I send a GET request to https://[@subdomain].chargify.com/customers/[@customer.id]/subscriptions.json
    Then the response status should be "200 OK"
    And the response should be a json array with 2 "subscription" objects

XML Read Usage Example


Feature: Chargify Subscriptions Read/Show/Lookup XML API
  In order integrate my app with Chargify
  As a developer
  I want to read/show/lookup a subscription via the Chargify XML API

  Background:
    Given I am a valid API user
    And I accept xml responses

  Scenario: Retrieve a subscription via ID
    Given I have an active subscription with ID "1000"
    When I send a GET request to https://acme.chargify.com/subscriptions/1000.xml
    Then the response status should be "200 OK"
    And the response should be the xml:
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <id type="integer">[@subscription.id]</id>
        <state>active</state>
        <previous_state>`auto generated`</previous_state>
        <balance_in_cents type="integer">0</balance_in_cents>
        <total_revenue_in_cents type="integer">1000</total_revenue_in_cents>
        <product_price_in_cents type="integer">`your value`</product_price_in_cents>
        <product_version_number type="integer">1</product_version_number>
        <current_period_started_at type="datetime">`auto generated`</current_period_started_at>
        <current_period_ends_at type="datetime">`auto generated`</current_period_ends_at>
        <next_assessment_at type="datetime">`auto generated`</next_assessment_at>
        <trial_started_at type="datetime">`auto generated`</trial_started_at>
        <trial_ended_at type="datetime">`auto generated`</trial_ended_at>
        <activated_at type="datetime">`auto generated`</activated_at>
        <expires_at type="datetime">`auto generated`</expires_at>
        <created_at type="datetime">`auto generated`</created_at>
        <updated_at type="datetime">`auto generated`</updated_at>
        <canceled_at type="datetime">`auto generated`</canceled_at>
        <cancellation_message nil="true"></cancellation_message>
        <cancel_at_end_of_period type="boolean">false</cancel_at_end_of_period>
        <delayed_cancel_at nil="true"></delayed_cancel_at>
        <coupon_code nil="true"></coupon_code>
        <signup_payment_id type="integer">`auto generated`</signup_payment_id>
        <signup_revenue>`your value`</signup_revenue>
        <payment_collection_method>automatic</payment_collection_method>
        <current_billing_amount_in_cents>1000</current_billing_amount_in_cents>
        <customer>
          <id type="integer">`auto generated`</id>
          <first_name>`your value`</first_name>
          <last_name>`your value`</last_name>
          <email>`your value`</email>
          <organization>`your value`</organization>
          <reference>`your value`</reference>
          <address>`your value`</address>
          <address_2>`your value`</address_2>
          <city>`your value`</city>
          <state>`your value`</state>
          <zip>`your value`</zip>
          <country>`your value`</country>
          <phone>`your value`</phone>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at>`auto generated`</updated_at>
        </customer>
        <product>
          <id>`auto generated`</id>
          <accounting_code>`your value`</accounting_code>
          <handle>`your value`</handle>
          <description>`your value`</description>
          <interval>`your value`</interval>
          <interval_unit>`your value`</interval_unit>
          <name>`your value`</name>
          <price_in_cents>`your value`</price_in_cents>
          <initial_charge_in_cents type="integer" nil="true"></initial_charge_in_cents>
          <trial_interval type="integer" nil="true"></trial_interval>
          <trial_interval_unit nil="true"></trial_interval_unit>
          <trial_price_in_cents type="integer" nil="true"></trial_price_in_cents>
          <expiration_interval type="integer">`your value`</expiration_interval>
          <expiration_interval_unit>`your value`</expiration_interval_unit>
          <archived_at type="datetime" nil="true"></archived_at>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at type="datetime">`auto generated`</updated_at>
          <request_credit_card type="boolean">true</request_credit_card>
          <require_credit_card type="boolean">true</require_credit_card>
          <return_url nil="true"></return_url>
          <update_return_url nil="true"></update_return_url>
          <return_params nil="true"></return_params>
          <product_family>
            <id>`auto generated`</id>
            <accounting_code>`your value`</accounting_code>
            <handle>`your value`</handle>
            <name>`your value`</name>
            <description>`your value`</description>
          </product_family>
        </product>
        <credit_card type="PaymentProfile">
          <id type="integer">`auto generated`</id>
          <card_type>`auto generated`</card_type>
          <expiration_month>`your value`</expiration_month>
          <expiration_year type="integer">`your value`</expiration_year>
          <first_name>`your value`</first_name>
          <last_name>`your value`</last_name>
          <masked_card_number>`auto generated`</masked_card_number>
          <billing_address>`your value`</billing_address>
          <billing_address_2>`your value`</billing_address_2>
          <billing_city>`your value`</billing_city>
          <billing_state>`your value`</billing_state>
          <billing_zip>`your value`</billing_zip>
          <billing_country>`your value`</billing_country>
          <current_vault type="integer">`your value`</current_vault>
          <vault_token type="integer">`your value`</vault_token>
          <customer_vault_token>`your value`</customer_vault_token>
          <customer_id>`auto generated`</customer_id>
        </credit_card>
      </subscription>
      """

  Scenario: Attempt to retrieve a subscription that doesn't exist
    Given I have 0 subscriptions
    When I send a GET request to https://[@subdomain].chargify.com/subscriptions/9999.xml
    Then the response status should be "404 Not Found"

JSON Read Usage Example


Feature: Chargify Subscriptions Read/Show/Lookup JSON API
  In order integrate my app with Chargify
  As a developer
  I want to read/show/lookup a subscription via the Chargify JSON API

  Background:
    Given I am a valid API user
    And I accept json responses

  Scenario: Retrieve a subscription via ID
    Given I have an active subscription
    When I send a GET request to https://[@subdomain].chargify.com/subscriptions/[@subscription.id].json
    Then the response status should be "200 OK"
    And the response should be the json:
      """
      {"subscription":{
        "id":[@subscription.id],
        "state":"active",
        "previous_state":`auto generated`,
        "balance_in_cents":0,
        "total_revenue_in_cents":1000,
        "product_price_in_cents": 1000,
        "product_version_number": 1,
        "current_period_started_at":`auto generated`,
        "current_period_ends_at":`auto generated`,
        "next_assessment_at":`auto generated`,
        "activated_at":`auto generated`,
        "trial_ended_at":`auto generated`,
        "trial_started_at":`auto generated`,
        "expires_at":`auto generated`,
        "created_at":`auto generated`,
        "updated_at":`auto generated`,
        "cancellation_message":null,
        "canceled_at":`your value`,
        "cancel_at_end_of_period":false,
        "delayed_cancel_at":null,
        "coupon_code":`your value`,
        "signup_payment_id":`auto generated`,
        "signup_revenue":`your value`,
        "payment_collection_method":"automatic",
        "current_billing_amount_in_cents": "1000",
        "customer":{
          "id":`auto generated`,
          "first_name":`your value`,
          "last_name":`your value`,
          "email":`your value`,
          "organization":`your value`,
          "reference":`your value`,
          "address":`your value`,
          "address_2":`your value`,
          "city":`your value`,
          "state":`auto generated`,
          "zip":`auto generated`,
          "country":`auto generated`,
          "phone":`auto generated`,
          "updated_at":`auto generated`,
          "created_at":`auto generated`
        },
        "product":{
          "id":`auto generated`,
          "name":`your value`,
          "handle":`your value`,
          "description":`your value`,
          "price_in_cents":`your value`,
          "accounting_code":`your value`,
          "interval":`your value`,
          "interval_unit":`your value`,
          "initial_charge_in_cents":null,
          "trial_price_in_cents":null,
          "trial_interval":null,
          "trial_interval_unit":null,
          "expiration_interval_unit":null,
          "expiration_interval":null,
          "return_url":null,
          "update_return_url":null,
          "return_params":null,
          "require_credit_card":true,
          "request_credit_card":true,
          "created_at":`auto generated`,
          "updated_at":`auto generated`,
          "archived_at":null,
          "product_family":{
            "id":`auto generated`,
            "name":`your value`,
            "handle":`your value`,
            "accounting_code":`your value`,
            "description":`your value`
          }
        },
        "credit_card":{
          "id":`auto generated`,
          "first_name":`your value`,
          "last_name":`your value`,
          "masked_card_number":`your value`,
          "card_type":`auto generated`,
          "expiration_month":`your value`,
          "expiration_year":`your value`,
          "billing_address":`your value`,
          "billing_address_2":`your value`,
          "billing_city":`your value`,
          "billing_state":`your value`,
          "billing_zip":`your value`,
          "billing_country":`your value`,
          "current_vault":`your value`,
          "vault_token":`your value`,
          "customer_vault_token":`your value`,
          "customer_id":`auto generated`
        }
      }}
      """

  Scenario: Attempt to retrieve a subscription that doesn't exist
    Given I have 0 subscriptions
    When I send a GET request to https://[@subdomain].chargify.com/subscriptions/9999.json
    Then the response status should be "404 Not Found"

XML Create Usage Example


Feature: Chargify Subscriptions Create XML API
  In order to integrate my app with Chargify
  As a developer
  I want to create a subscription via the Chargify XML API

  Background:
    Given I am a valid API user for site with subdomain "acme"
    And I send and accept xml

  Scenario: Create a subscription successfully with customer data, credit card data, and a product handle
    Given I have 1 product
    And I have this xml subscription data
      """
        <?xml version="1.0" encoding="UTF-8"?>
        <subscription>
          <product_handle>[@product.handle]</product_handle>
          <customer_attributes>
            <first_name>Joe</first_name>
            <last_name>Blow</last_name>
            <email>joe@example.com</email>
          </customer_attributes>
          <credit_card_attributes>
            <full_number>1</full_number>
            <expiration_month>10</expiration_month>
            <expiration_year>2020</expiration_year>
          </credit_card_attributes>
        </subscription>
      """
    When I send a POST request with the xml data to https://acme.chargify.com/subscriptions.xml
    Then the response status should be "201 Created"
    And the response should be the xml:
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <id type="integer">`auto generated`</id>
        <state>active</state>
        <previous_state>`auto generated`</previous_state>
        <balance_in_cents type="integer">`auto generated`</balance_in_cents>
        <total_revenue_in_cents type="integer">`auto generated`</total_revenue_in_cents>
        <product_price_in_cents type="integer">`your value`</product_price_in_cents>
        <product_version_number type="integer">1</product_version_number>
        <current_period_started_at type="datetime">`auto generated`</current_period_started_at>
        <current_period_ends_at type="datetime">`auto generated`</current_period_ends_at>
        <next_assessment_at type="datetime">`auto generated`</next_assessment_at>
        <trial_started_at type="datetime">`auto generated`</trial_started_at>
        <trial_ended_at type="datetime">`auto generated`</trial_ended_at>
        <activated_at type="datetime">`auto generated`</activated_at>
        <expires_at type="datetime">`auto generated`</expires_at>
        <created_at type="datetime">`auto generated`</created_at>
        <updated_at type="datetime">`auto generated`</updated_at>
        <canceled_at type="datetime">`auto generated`</canceled_at>
        <cancellation_message nil="true"></cancellation_message>
        <cancel_at_end_of_period type="boolean">false</cancel_at_end_of_period>
        <delayed_cancel_at nil="true"></delayed_cancel_at>
        <coupon_code nil="true"></coupon_code>
        <signup_payment_id type="integer">`auto generated`</signup_payment_id>
        <signup_revenue>`your value`</signup_revenue>
        <payment_collection_method>automatic</payment_collection_method>
        <customer>
          <id type="integer">`auto generated`</id>
          <first_name>Joe</first_name>
          <last_name>Blow</last_name>
          <email>joe@example.com</email>
          <organization>`your value`</organization>
          <reference>`your value`</reference>
          <address>`your value`</address>
          <address_2>`your value`</address_2>
          <city>`your value`</city>
          <state>`your value`</state>
          <zip>`your value`</zip>
          <country>`your value`</country>
          <phone>`your value`</phone>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at type="datetime">`auto generated`</updated_at>
        </customer>
        <product>
          <id>`auto generated`</id>
          <accounting_code>`your value`</accounting_code>
          <handle>[@product.handle]</handle>
          <description>`your value`</description>
          <interval>`your value`</interval>
          <interval_unit>`your value`</interval_unit>
          <name>`your value`</name>
          <price_in_cents>`your value`</price_in_cents>
          <initial_charge_in_cents type="integer" nil="true"></initial_charge_in_cents>
          <trial_interval type="integer" nil="true"></trial_interval>
          <trial_interval_unit nil="true"></trial_interval_unit>
          <trial_price_in_cents type="integer" nil="true"></trial_price_in_cents>
          <expiration_interval type="integer">`your value`</expiration_interval>
          <expiration_interval_unit>`your value`</expiration_interval_unit>
          <archived_at type="datetime" nil="true"></archived_at>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at type="datetime">`auto generated`</updated_at>
          <request_credit_card type="boolean">true</request_credit_card>
          <require_credit_card type="boolean">true</require_credit_card>
          <return_url nil="true"></return_url>
          <update_return_url nil="true"></update_return_url>
          <return_params nil="true"></return_params>
          <product_family>
            <id>`auto generated`</id>
            <accounting_code>`your value`</accounting_code>
            <handle>`your value`</handle>
            <name>`your value`</name>
            <description>`your value`</description>
          </product_family>
        </product>
        <credit_card type="PaymentProfile">
          <id type="integer">`auto generated`</id>
          <card_type>bogus</card_type>
          <expiration_month type="integer">10</expiration_month>
          <expiration_year type="integer">2020</expiration_year>
          <first_name>Joe</first_name>
          <last_name>Blow</last_name>
          <masked_card_number>XXXX-XXXX-XXXX-1</masked_card_number>
          <billing_address>`your value`</billing_address>
          <billing_address_2>`your value`</billing_address_2>
          <billing_city>`your value`</billing_city>
          <billing_state>`your value`</billing_state>
          <billing_zip>`your value`</billing_zip>
          <billing_country>`your value`</billing_country>
          <current_vault type="integer">`your value`</current_vault>
          <vault_token type="integer">`your value`</vault_token>
          <customer_vault_token>`your value`</customer_vault_token>
          <customer_id>`auto generated`</customer_id>
        </credit_card>
      </subscription>
      """
    And the subscription's channel attribute should be set to "api"

  Scenario: Create a subscription using an existing customer ID
    Given I have 1 product
    And I have 1 customer
    And I have this xml subscription data
      """
        <?xml version="1.0" encoding="UTF-8"?>
        <subscription>
          <product_handle>[@product.handle]</product_handle>
          <customer_id type="integer">[@customer.id]</customer_id>
          <credit_card_attributes>
            <full_number>1</full_number>
            <expiration_month>10</expiration_month>
            <expiration_year>2020</expiration_year>
          </credit_card_attributes>
        </subscription>
      """
    When I send a POST request with the xml data to https://acme.chargify.com/subscriptions.xml
    Then the response status should be "201 Created"


  Scenario: Create a subscription using an existing customer reference
    Given I have 1 product
    And I have a customer with these attributes
      | reference | first_name | last_name | email           |
      | 7890      | Joe        | Blow      | joe@example.com |
    And I have this xml subscription data
      """
        <?xml version="1.0" encoding="UTF-8"?>
        <subscription>
          <product_handle>[@product.handle]</product_handle>
          <customer_reference>[@customer.reference]</customer_reference>
          <credit_card_attributes>
            <full_number>1</full_number>
            <expiration_month>10</expiration_month>
            <expiration_year>2020</expiration_year>
          </credit_card_attributes>
        </subscription>
      """
    When I send a POST request with the xml data to https://acme.chargify.com/subscriptions.xml
    Then the response status should be "201 Created"


  Scenario: Creating a subscription fails due to missing or invalid attributes
    Given I have 1 product
    And I have this xml subscription data
      """
        <?xml version="1.0" encoding="UTF-8"?>
        <subscription>
          <product_handle>[@product.handle]</product_handle>
          <customer_attributes>
            <first_name>Joe</first_name>
          </customer_attributes>
          <credit_card_attributes>
            <full_number>1</full_number>
          </credit_card_attributes>
        </subscription>
      """
    When I send a POST request with the xml data to https://acme.chargify.com/subscriptions.xml
    Then the response status should be "422 Unprocessable Entity"
    And the response should be the xml:
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <errors>
        <error>Credit card expiration year: cannot be blank.</error>
        <error>Last name: cannot be blank.</error>
        <error>Credit card expiration month: cannot be blank.</error>
        <error>Email address: cannot be blank.</error>
      </errors>
      """


  Scenario: Creating a subscription fails due to a missing product
    Given I have 1 product
    And I have this xml subscription data
      """
        <?xml version="1.0" encoding="UTF-8"?>
        <subscription>
          <product_handle>this-does-not-exist</product_handle>
          <customer_attributes>
            <first_name>Joe</first_name>
            <last_name>Blow</last_name>
            <email>joe@example.com</email>
          </customer_attributes>
          <credit_card_attributes>
            <full_number>1</full_number>
            <expiration_month>10</expiration_month>
            <expiration_year>2020</expiration_year>
          </credit_card_attributes>
        </subscription>
      """
    When I send a POST request with the xml data to https://acme.chargify.com/subscriptions.xml
    Then the response status should be "422 Unprocessable Entity"
    And the response should be the xml:
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <errors>
        <error>Product with API Handle 'this-does-not-exist' does not exist for this site.</error>
      </errors>
      """

  Scenario: Creating a subscription fails if only a 2 digit date expiration year is passed
    Given I have 1 product
    And I have this xml subscription data
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <product_handle>[@product.handle]</product_handle>
        <customer_attributes>
          <first_name>Joe</first_name>
          <last_name>Blow</last_name>
          <email>joe@example.com</email>
        </customer_attributes>
        <credit_card_attributes>
          <full_number>1</full_number>
          <expiration_month>10</expiration_month>
          <expiration_year>2000</expiration_year>
        </credit_card_attributes>
      </subscription>
      """
    When I send a POST request with the xml data to https://acme.chargify.com/subscriptions.xml
    Then the response status should be "422 Unprocessable Entity"
    And the response should be the xml:
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <errors>
        <error>Credit card: cannot be expired.</error>
      </errors>
      """

  Scenario: Create a subscription successfully with a coupon
    Given I have 1 product
    And I have a $5 off coupon with the code "EARLYBIRD"
    And I have this xml subscription data
      """
        <?xml version="1.0" encoding="UTF-8"?>
        <subscription>
          <product_handle>[@product.handle]</product_handle>
          <customer_attributes>
            <first_name>Joe</first_name>
            <last_name>Blow</last_name>
            <email>joe@example.com</email>
          </customer_attributes>
          <credit_card_attributes>
            <full_number>1</full_number>
            <expiration_month>10</expiration_month>
            <expiration_year>2020</expiration_year>
          </credit_card_attributes>
          <coupon_code>EARLYBIRD</coupon_code>
        </subscription>
      """
    When I send a POST request with the xml data to https://acme.chargify.com/subscriptions.xml
    Then the response status should be "201 Created"
    And the response should be the xml:
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <id type="integer">`auto generated`</id>
        <state>active</state>
        <previous_state>`auto generated`</previous_state>
        <balance_in_cents type="integer">`auto generated`</balance_in_cents>
        <total_revenue_in_cents type="integer">`auto generated`</total_revenue_in_cents>
        <product_price_in_cents type="integer">`your value`</product_price_in_cents>
        <product_version_number type="integer">1</product_version_number>
        <current_period_started_at type="datetime">`auto generated`</current_period_started_at>
        <current_period_ends_at type="datetime">`auto generated`</current_period_ends_at>
        <next_assessment_at type="datetime">`auto generated`</next_assessment_at>
        <trial_started_at type="datetime">`auto generated`</trial_started_at>
        <trial_ended_at type="datetime">`auto generated`</trial_ended_at>
        <activated_at type="datetime">`auto generated`</activated_at>
        <expires_at type="datetime">`auto generated`</expires_at>
        <created_at type="datetime">`auto generated`</created_at>
        <updated_at type="datetime">`auto generated`</updated_at>
        <canceled_at type="datetime">`auto generated`</canceled_at>
        <cancellation_message nil="true"></cancellation_message>
        <cancel_at_end_of_period type="boolean" nil="true"></cancel_at_end_of_period>
        <delayed_cancel_at nil="true"></delayed_cancel_at>
        <coupon_code>EARLYBIRD</coupon_code>
        <signup_payment_id type="integer">`auto generated`</signup_payment_id>
        <signup_revenue>`your value`</signup_revenue>
        <payment_collection_method>automatic</payment_collection_method>
        <customer>
          <id type="integer">`auto generated`</id>
          <first_name>Joe</first_name>
          <last_name>Blow</last_name>
          <email>joe@example.com</email>
          <organization>`your value`</organization>
          <reference>`your value`</reference>
          <address>`your value`</address>
          <address_2>`your value`</address_2>
          <city>`your value`</city>
          <state>`your value`</state>
          <zip>`your value`</zip>
          <country>`your value`</country>
          <phone>`your value`</phone>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at type="datetime">`auto generated`</updated_at>
        </customer>
        <product>
          <id>`auto generated`</id>
          <accounting_code>`your value`</accounting_code>
          <handle>[@product.handle]</handle>
          <description>`your value`</description>
          <interval>`your value`</interval>
          <interval_unit>`your value`</interval_unit>
          <name>`your value`</name>
          <price_in_cents>`your value`</price_in_cents>
          <initial_charge_in_cents type="integer" nil="true"></initial_charge_in_cents>
          <trial_interval type="integer" nil="true"></trial_interval>
          <trial_interval_unit nil="true"></trial_interval_unit>
          <trial_price_in_cents type="integer" nil="true"></trial_price_in_cents>
          <expiration_interval type="integer">`your value`</expiration_interval>
          <expiration_interval_unit>`your value`</expiration_interval_unit>
          <archived_at type="datetime" nil="true"></archived_at>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at type="datetime">`auto generated`</updated_at>
          <request_credit_card type="boolean">true</request_credit_card>
          <require_credit_card type="boolean">true</require_credit_card>
          <return_url nil="true"></return_url>
          <update_return_url nil="true"></update_return_url>
          <return_params nil="true"></return_params>
          <product_family>
            <id>`auto generated`</id>
            <accounting_code>`your value`</accounting_code>
            <handle>`your value`</handle>
            <name>`your value`</name>
            <description>`your value`</description>
          </product_family>
        </product>
        <credit_card type="PaymentProfile">
          <id type="integer">`auto generated`</id>
          <card_type>bogus</card_type>
          <expiration_month type="integer">10</expiration_month>
          <expiration_year type="integer">2020</expiration_year>
          <first_name>Joe</first_name>
          <last_name>Blow</last_name>
          <masked_card_number>XXXX-XXXX-XXXX-1</masked_card_number>
          <billing_address>`your value`</billing_address>
          <billing_address_2>`your value`</billing_address_2>
          <billing_city>`your value`</billing_city>
          <billing_state>`your value`</billing_state>
          <billing_zip>`your value`</billing_zip>
          <billing_country>`your value`</billing_country>
          <current_vault type="integer">`your value`</current_vault>
          <vault_token type="integer">`your value`</vault_token>
          <customer_vault_token>`your value`</customer_vault_token>
          <customer_id>`auto generated`</customer_id>
        </credit_card>
      </subscription>
      """
    And I should have 1 subscription
    And the subscription should have 1 coupon
    And the coupon should have been applied

    Scenario: Create a subscription successfully when a tax is applicable
      Given I have 1 product
      And the product is taxable
      And I have a tax named "PA Sales Tax"
      And the tax applies to the customer's location
      And I have this xml subscription data
        """
          <?xml version="1.0" encoding="UTF-8"?>
          <subscription>
            <product_handle>[@product.handle]</product_handle>
            <customer_attributes>
              <first_name>Joe</first_name>
              <last_name>Blow</last_name>
              <email>joe@example.com</email>
              <country>US</country>
              <state>PA</state>
            </customer_attributes>
            <credit_card_attributes>
              <full_number>1</full_number>
              <expiration_month>10</expiration_month>
              <expiration_year>2020</expiration_year>
            </credit_card_attributes>
          </subscription>
        """
      When I send a POST request with the xml data to https://acme.chargify.com/subscriptions.xml
      Then the response status should be "201 Created"
      And a charge for the tax should have been created

    Scenario: Create a subscription for a product with an empty credit card
      Given I have 1 product
      And I have this xml subscription data
        """
          <?xml version="1.0" encoding="UTF-8"?>
          <subscription>
            <product_handle>[@product.handle]</product_handle>
            <customer_attributes>
              <first_name>Joe</first_name>
              <last_name>Blow</last_name>
              <email>joe@example.com</email>
              <country>US</country>
              <state>PA</state>
            </customer_attributes>
            <credit_card_attributes>
            </credit_card_attributes>
          </subscription>
        """
      When I send a POST request with the xml data to https://acme.chargify.com/subscriptions.xml
      Then the response status should be "422 Unprocessable Entity"

    Scenario: Create a subscription for a product with empty customer params
      Given I have 1 product
      And I have this xml subscription data
        """
          <?xml version="1.0" encoding="UTF-8"?>
          <subscription>
            <product_handle>[@product.handle]</product_handle>
            <customer_attributes>
            </customer_attributes>
            <credit_card_attributes>
              <full_number>1</full_number>
              <expiration_month>10</expiration_month>
              <expiration_year>2020</expiration_year>
            </credit_card_attributes>
          </subscription>
        """
      When I send a POST request with the xml data to https://acme.chargify.com/subscriptions.xml
      Then the response status should be "422 Unprocessable Entity"

JSON Create Usage Example


Feature: Chargify Subscriptions Create JSON API
  In order to integrate my app with Chargify
  As a developer
  I want to create a subscription via the Chargify JSON API

  Background:
    Given I am a valid API user for site with subdomain "acme"
    And I send and accept json

  Scenario: Create a subscription successfully with customer data, credit card data, and a product handle
    Given site "acme" has a product with handle "basic"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_attributes":{
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com"
        },
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020"
        }
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"
    And the response should be the json:
      """
      {"subscription":{
        "id":`auto generated`,
        "state":"active",
        "previous_state":`auto generated`,
        "balance_in_cents": 0,
        "total_revenue_in_cents": 1000,
        "product_price_in_cents": 1000,
        "product_version_number": 1,
        "current_period_started_at":`auto generated`,
        "current_period_ends_at":`auto generated`,
        "next_assessment_at":`auto generated`,
        "activated_at":`auto generated`,
        "trial_ended_at":`auto generated`,
        "trial_started_at":`auto generated`,
        "expires_at":`auto generated`,
        "created_at":`auto generated`,
        "updated_at":`auto generated`,
        "canceled_at":`your value`,
        "signup_payment_id":`auto generated`,
        "signup_revenue":`your value`,
        "cancellation_message":null,
        "cancel_at_end_of_period":false,
        "delayed_cancel_at":null,
        "coupon_code":`your value`,
        "payment_collection_method":"automatic",
        "customer":{
          "id":`auto generated`,
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com",
          "organization":`your value`,
          "reference":`your value`,
          "address":`your value`,
          "address_2":`your value`,
          "city":`your value`,
          "state":`auto generated`,
          "zip":`auto generated`,
          "country":`auto generated`,
          "phone":`auto generated`,
          "updated_at":`auto generated`,
          "created_at":`auto generated`
        },
        "product":{
          "id":`auto generated`,
          "name":`your value`,
          "handle":"basic",
          "price_in_cents":`your value`,
          "accounting_code":`your value`,
          "description":`your value`,
          "interval":`your value`,
          "interval_unit":`your value`,
          "initial_charge_in_cents":null,
          "trial_price_in_cents":null,
          "trial_interval":null,
          "trial_interval_unit":null,
          "expiration_interval_unit":null,
          "expiration_interval":null,
          "return_url":null,
          "update_return_url":null,
          "return_params":null,
          "require_credit_card":true,
          "request_credit_card":true,
          "created_at":`auto generated`,
          "updated_at":`auto generated`,
          "archived_at":null,
          "product_family":{
            "id":`auto generated`,
            "name":`your value`,
            "handle":`your value`,
            "accounting_code":`your value`,
            "description":`your value`
          }
        },
        "credit_card":{
          "id":`auto generated`,
          "first_name":"Joe",
          "last_name":"Blow",
          "masked_card_number":"XXXX-XXXX-XXXX-1",
          "card_type":`auto generated`,
          "expiration_month":10,
          "expiration_year":2020,
          "billing_address":`your value`,
          "billing_address_2":`your value`,
          "billing_city":`your value`,
          "billing_state":`your value`,
          "billing_zip":`your value`,
          "billing_country":`your value`,
          "current_vault":`your value`,
          "vault_token":`your value`,
          "customer_vault_token":`your value`,
          "customer_id":`auto generated`
        }
      }}
      """

  Scenario: Create a subscription using an existing customer ID
    Given site "acme" has a product with handle "basic"
    And site "acme" has a customer with ID "2000"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_id":2000,
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020"
        }
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"


  Scenario: Create a subscription using an existing customer reference
    Given site "acme" has a product with handle "basic"
    And I have a customer with these attributes
      | reference | first_name | last_name | email           |
      | 7890      | Joe        | Blow      | joe@example.com |
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_reference":"7890",
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020"
        }
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"

  Scenario: Creating a subscription fails due to missing or invalid attributes
    Given site "acme" has a product with handle "basic"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_attributes":{
          "first_name":"Joe"
        },
        "credit_card_attributes":{
          "full_number":"1"
        }
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "422 Unprocessable Entity"
    And the response should be the json:
      """
      {"errors":
        [
          "Credit card expiration year: cannot be blank.",
          "Last name: cannot be blank.",
          "Credit card expiration month: cannot be blank.",
          "Email address: cannot be blank."
        ]
      }
      """

  Scenario: Creating a subscription fails due to a missing product
    Given I have this json subscription data
      """
      {"subscription":{
        "product_handle":"this-does-not-exist",
        "customer_attributes":{
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com"
        },
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020"
        }
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "422 Unprocessable Entity"
    And the response should be the json:
      """
      {"errors":
        [
          "Product with API Handle 'this-does-not-exist' does not exist for this site."
        ]
      }
      """

  Scenario: Create a subscription successfully with a coupon
    Given site "acme" has a product with handle "basic"
    And I have a $5 off coupon with the code "EARLYBIRD"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_attributes":{
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com"
        },
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020"
        },
        "coupon_code":"EARLYBIRD"
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"
    And the response should be the json:
      """
      {"subscription":{
        "id":`auto generated`,
        "state":"active",
        "previous_state":`auto generated`,
        "balance_in_cents":`auto generated`,
        "total_revenue_in_cents":`auto generated`,
        "product_price_in_cents": 1000,
        "product_version_number": 1,
        "current_period_started_at":`auto generated`,
        "current_period_ends_at":`auto generated`,
        "next_assessment_at":`auto generated`,
        "activated_at":`auto generated`,
        "trial_ended_at":`auto generated`,
        "trial_started_at":`auto generated`,
        "expires_at":`auto generated`,
        "created_at":`auto generated`,
        "updated_at":`auto generated`,
        "canceled_at":`your value`,
        "signup_payment_id":`auto generated`,
        "signup_revenue":`your value`,
        "cancellation_message":null,
        "cancel_at_end_of_period":null,
        "delayed_cancel_at":null,
        "coupon_code":"EARLYBIRD",
        "payment_collection_method":"automatic",
        "customer":{
          "id":`auto generated`,
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com",
          "organization":`your value`,
          "reference":`your value`,
          "address":`your value`,
          "address_2":`your value`,
          "city":`your value`,
          "state":`auto generated`,
          "zip":`auto generated`,
          "country":`auto generated`,
          "phone":`auto generated`,
          "updated_at":`auto generated`,
          "created_at":`auto generated`
        },
        "product":{
          "id":`auto generated`,
          "name":`your value`,
          "handle":"basic",
          "price_in_cents":`your value`,
          "accounting_code":`your value`,
          "description":`your value`,
          "interval":`your value`,
          "interval_unit":`your value`,
          "initial_charge_in_cents":null,
          "trial_price_in_cents":null,
          "trial_interval":null,
          "trial_interval_unit":null,
          "expiration_interval_unit":null,
          "expiration_interval":null,
          "return_url":null,
          "update_return_url":null,
          "return_params":null,
          "require_credit_card":true,
          "request_credit_card":true,
          "created_at":`auto generated`,
          "updated_at":`auto generated`,
          "archived_at":null,
          "product_family":{
            "id":`auto generated`,
            "name":`your value`,
            "handle":`your value`,
            "accounting_code":`your value`,
            "description":`your value`
          }
        },
        "credit_card":{
          "id":`auto generated`,
          "first_name":"Joe",
          "last_name":"Blow",
          "masked_card_number":"XXXX-XXXX-XXXX-1",
          "card_type":`auto generated`,
          "expiration_month":10,
          "expiration_year":2020,
          "billing_address":`your value`,
          "billing_address_2":`your value`,
          "billing_city":`your value`,
          "billing_state":`your value`,
          "billing_zip":`your value`,
          "billing_country":`your value`,
          "current_vault":`your value`,
          "vault_token":`your value`,
          "customer_vault_token":`your value`,
          "customer_id":`auto generated`
        }
      }}
      """
    And I should have 1 subscription
    And the subscription should have 1 coupon
    And the coupon should have been applied


  Scenario: Create a subscription successfully with a coupon subcode
    Given site "acme" has a product with handle "basic"
    And I have a $5 off coupon with the code "EARLYBIRD"
    And the coupon has the subcode "SUB111"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_attributes":{
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com"
        },
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020"
        },
        "coupon_code":"SUB111"
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"
    And I should have 1 subscription
    And the subscription should have 1 coupon
    And the coupon should have been applied
    And the adjustment's memo should include the coupon subcode "SUB111"


  Scenario: Create a subscription successfully with customer address and phone
    Given site "acme" has a product with handle "basic"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_attributes":{
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com",
          "address":"1 Infinite Loop",
          "address_2":"Suite 1",
          "city":"Cupertino",
          "state":"CA",
          "zip":"95014",
          "country":"US",
          "phone":"5552666666"
        },
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020"
        }
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"
    And the response should be the json:
      """
      {"subscription":{
        "id":`auto generated`,
        "state":"active",
        "previous_state":`auto generated`,
        "balance_in_cents":`auto generated`,
        "total_revenue_in_cents":`auto generated`,
        "product_price_in_cents": 1000,
        "product_version_number": 1,
        "current_period_started_at":`auto generated`,
        "current_period_ends_at":`auto generated`,
        "next_assessment_at":`auto generated`,
        "activated_at":`auto generated`,
        "trial_ended_at":`auto generated`,
        "trial_started_at":`auto generated`,
        "expires_at":`auto generated`,
        "created_at":`auto generated`,
        "updated_at":`auto generated`,
        "canceled_at":`your value`,
        "cancellation_message":null,
        "cancel_at_end_of_period":false,
        "delayed_cancel_at":null,
        "coupon_code":`your value`,
        "signup_payment_id":`auto generated`,
        "signup_revenue":`your value`,
        "payment_collection_method":"automatic",
        "customer":{
          "id":`auto generated`,
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com",
          "organization":`your value`,
          "reference":`your value`,
          "address":"1 Infinite Loop",
          "address_2":"Suite 1",
          "city":"Cupertino",
          "state":"CA",
          "zip":"95014",
          "country":"US",
          "phone":"5552666666",
          "updated_at":`auto generated`,
          "created_at":`auto generated`
        },
        "product":{
          "id":`auto generated`,
          "name":`your value`,
          "handle":"basic",
          "price_in_cents":`your value`,
          "accounting_code":`your value`,
          "description":`your value`,
          "interval":`your value`,
          "interval_unit":`your value`,
          "initial_charge_in_cents":null,
          "trial_price_in_cents":null,
          "trial_interval":null,
          "trial_interval_unit":null,
          "expiration_interval_unit":null,
          "expiration_interval":null,
          "return_url":null,
          "update_return_url":null,
          "return_params":null,
          "require_credit_card":true,
          "request_credit_card":true,
          "created_at":`auto generated`,
          "updated_at":`auto generated`,
          "archived_at":null,
          "product_family":{
            "id":`auto generated`,
            "name":`your value`,
            "handle":`your value`,
            "accounting_code":`your value`,
            "description":`your value`
          }
        },
        "credit_card":{
          "id":`auto generated`,
          "first_name":"Joe",
          "last_name":"Blow",
          "masked_card_number":"XXXX-XXXX-XXXX-1",
          "card_type":`auto generated`,
          "expiration_month":10,
          "expiration_year":2020,
          "billing_address":`your value`,
          "billing_address_2":`your value`,
          "billing_city":`your value`,
          "billing_state":`your value`,
          "billing_zip":`your value`,
          "billing_country":`your value`,
          "current_vault":`your value`,
          "vault_token":`your value`,
          "customer_vault_token":`your value`,
          "customer_id":`auto generated`
        }
      }}
      """

  Scenario: Create a subscription successfully with billing address
    Given site "acme" has a product with handle "basic"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_attributes":{
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com",
          "address":"1 Infinite Loop",
          "address_2":"Suite 1",
          "city":"Cupertino",
          "state":"CA",
          "zip":"95014",
          "country":"US",
          "phone":"5552666666"
        },
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020",
          "billing_address":"1 Infinite Loop",
          "billing_address_2":"Suite 1",
          "billing_city":"Cupertino",
          "billing_state":"CA",
          "billing_zip":"95014",
          "billing_country":"US"
        }
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"
    And the response should be the json:
      """
      {"subscription":{
        "id":`auto generated`,
        "state":"active",
        "previous_state":`auto generated`,
        "balance_in_cents":`auto generated`,
        "total_revenue_in_cents":`auto generated`,
        "product_price_in_cents": 1000,
        "product_version_number": 1,
        "current_period_started_at":`auto generated`,
        "current_period_ends_at":`auto generated`,
        "next_assessment_at":`auto generated`,
        "activated_at":`auto generated`,
        "trial_ended_at":`auto generated`,
        "trial_started_at":`auto generated`,
        "expires_at":`auto generated`,
        "created_at":`auto generated`,
        "updated_at":`auto generated`,
        "canceled_at":`your value`,
        "cancellation_message":null,
        "cancel_at_end_of_period":false,
        "delayed_cancel_at":null,
        "coupon_code":`your value`,
        "signup_payment_id":`auto generated`,
        "signup_revenue":`your value`,
        "payment_collection_method":"automatic",
        "customer":{
          "id":`auto generated`,
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com",
          "organization":`your value`,
          "reference":`your value`,
          "address":"1 Infinite Loop",
          "address_2":"Suite 1",
          "city":"Cupertino",
          "state":"CA",
          "zip":"95014",
          "country":"US",
          "phone":"5552666666",
          "updated_at":`auto generated`,
          "created_at":`auto generated`
        },
        "product":{
          "id":`auto generated`,
          "name":`your value`,
          "handle":"basic",
          "price_in_cents":`your value`,
          "accounting_code":`your value`,
          "description":`your value`,
          "interval":`your value`,
          "interval_unit":`your value`,
          "initial_charge_in_cents":null,
          "trial_price_in_cents":null,
          "trial_interval":null,
          "trial_interval_unit":null,
          "expiration_interval_unit":null,
          "expiration_interval":null,
          "return_url":null,
          "update_return_url":null,
          "return_params":null,
          "require_credit_card":true,
          "request_credit_card":true,
          "created_at":`auto generated`,
          "updated_at":`auto generated`,
          "archived_at":null,
          "product_family":{
            "id":`auto generated`,
            "name":`your value`,
            "handle":`your value`,
            "accounting_code":`your value`,
            "description":`your value`
          }
        },
        "credit_card":{
          "id":`auto generated`,
          "first_name":"Joe",
          "last_name":"Blow",
          "masked_card_number":"XXXX-XXXX-XXXX-1",
          "card_type":`auto generated`,
          "expiration_month":10,
          "expiration_year":2020,
          "billing_address":"1 Infinite Loop",
          "billing_address_2":"Suite 1",
          "billing_city":"Cupertino",
          "billing_state":"CA",
          "billing_zip":"95014",
          "billing_country":"US",
          "current_vault":`your value`,
          "vault_token":`your value`,
          "customer_vault_token":`your value`,
          "customer_id":`auto generated`
        }
      }}
      """
  Scenario: Creating a subscription with a specified billing date
    Given site "acme" has a product with handle "basic"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_attributes":{
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com"
        },
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020"
        },
        "next_billing_at":"2020-06-01"
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"
    And the subscription's channel attribute should be set to "api"

  Scenario: Create a subscription successfully when a tax is applicable
    Given site "acme" has a product with handle "basic"
    And the product is taxable
    And I have a tax named "PA Sales Tax"
    And the tax applies to the customer's location
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_attributes":{
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com",
          "state":"PA",
          "country":"US"
        },
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020"
        }
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"
    And a charge for the tax should have been created

  Scenario: Create a subscription successfully with an on-off component
    Given site "acme" has a product with handle "basic"
    And the product family has an on/off component with ID "2500"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_attributes":{
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com"
        },
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020"
        },
        "components": [{
          "component_id": 2500,
          "enabled": true
        }]
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"
    And and the component will be toggled "on" for the subscription 

  Scenario: Create a subscription successfully with a quantity-based component
    Given site "acme" has a product with handle "basic"
    And the product family has a quantity-based component with ID "2500"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_attributes":{
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com"
        },
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2020"
        },
        "components": [{
          "component_id": 2500,
          "allocated_quantity": 14
        }]
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"
    And the allocated quantity should be 14

  Scenario: Create a subscription successfully with customer data, credit card data, and a product handle
    Given site "acme" has a product with handle "basic"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle":"basic",
        "customer_attributes":{
          "first_name":"Joe",
          "last_name":"Blow",
          "email":"joe@example.com"
        },
        "credit_card_attributes":{
          "full_number":"1",
          "expiration_month":"10",
          "expiration_year":"2016"
        }
      }}
      """
    When I send a POST request with the json data to https://acme.chargify.com/subscriptions.json
    Then the response status should be "201 Created"

XML Update Usage Example


Feature: Chargify Subscriptions Edit/Update XML API
  In order to integrate my app with Chargify
  As a developer
  I want to edit/update a subscription via the Chargify XML API

  Background:
    Given I am a valid API user for site with subdomain "acme"
    And I send and accept xml

  Scenario: Update the credit card information on a subscription using credit_card_attributes
    Given I have an active subscription with ID "1000"
    And I have this xml subscription data
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <credit_card_attributes>
          <full_number>2</full_number>
          <expiration_month>10</expiration_month>
          <expiration_year>2040</expiration_year>
        </credit_card_attributes>
      </subscription>
      """
    When I send a PUT request with the xml data to https://acme.chargify.com/subscriptions/1000.xml
    Then the response status should be "200 OK"
    And the response should be the xml:
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <id type="integer">1000</id>
        <state>active</state>
        <previous_state>`auto generated`</previous_state>
        <balance_in_cents type="integer">0</balance_in_cents>
        <total_revenue_in_cents type="integer">`auto generated`</total_revenue_in_cents>
        <product_price_in_cents type="integer">`your value`</product_price_in_cents>
        <product_version_number type="integer">1</product_version_number>
        <current_period_started_at type="datetime">`auto generated`</current_period_started_at>
        <current_period_ends_at type="datetime">`auto generated`</current_period_ends_at>
        <next_assessment_at type="datetime">`auto generated`</next_assessment_at>
        <trial_started_at type="datetime">`auto generated`</trial_started_at>
        <trial_ended_at type="datetime">`auto generated`</trial_ended_at>
        <activated_at type="datetime">`auto generated`</activated_at>
        <expires_at type="datetime">`auto generated`</expires_at>
        <created_at type="datetime">`auto generated`</created_at>
        <updated_at type="datetime">`auto generated`</updated_at>
        <canceled_at type="datetime">`auto generated`</canceled_at>
        <cancellation_message nil="true"></cancellation_message>
        <cancel_at_end_of_period type="boolean">false</cancel_at_end_of_period>
        <delayed_cancel_at nil="true"></delayed_cancel_at>
        <coupon_code nil="true"></coupon_code>
        <signup_payment_id type="integer">`auto generated`</signup_payment_id>
        <signup_revenue>`your value`</signup_revenue>
        <payment_collection_method>automatic</payment_collection_method>
        <customer>
          <id type="integer">`auto generated`</id>
          <first_name>`your value`</first_name>
          <last_name>`your value`</last_name>
          <email>`your value`</email>
          <organization>`your value`</organization>
          <reference>`your value`</reference>
          <address>`your value`</address>
          <address_2>`your value`</address_2>
          <city>`your value`</city>
          <state>`your value`</state>
          <zip>`your value`</zip>
          <country>`your value`</country>
          <phone>`your value`</phone>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at>`auto generated`</updated_at>
        </customer>
        <product>
          <id>`auto generated`</id>
          <accounting_code>`your value`</accounting_code>
          <handle>`your value`</handle>
          <description>`your value`</description>
          <interval>`your value`</interval>
          <interval_unit>`your value`</interval_unit>
          <name>`your value`</name>
          <price_in_cents>`your value`</price_in_cents>
          <initial_charge_in_cents type="integer" nil="true"></initial_charge_in_cents>
          <trial_interval type="integer" nil="true"></trial_interval>
          <trial_interval_unit nil="true"></trial_interval_unit>
          <trial_price_in_cents type="integer" nil="true"></trial_price_in_cents>
          <expiration_interval type="integer">`your value`</expiration_interval>
          <expiration_interval_unit>`your value`</expiration_interval_unit>
          <archived_at type="datetime" nil="true"></archived_at>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at type="datetime">`auto generated`</updated_at>
          <request_credit_card type="boolean">true</request_credit_card>
          <require_credit_card type="boolean">true</require_credit_card>
          <return_url nil="true"></return_url>
          <update_return_url nil="true"></update_return_url>
          <return_params nil="true"></return_params>
          <product_family>
            <id>`auto generated`</id>
            <accounting_code>`your value`</accounting_code>
            <handle>`your value`</handle>
            <name>`your value`</name>
            <description>`your value`</description>
          </product_family>
        </product>
        <credit_card type="PaymentProfile">
          <id type="integer">`auto generated`</id>
          <card_type>`auto generated`</card_type>
          <expiration_month type="integer">10</expiration_month>
          <expiration_year type="integer">2040</expiration_year>
          <first_name>`your value`</first_name>
          <last_name>`your value`</last_name>
          <masked_card_number>XXXX-XXXX-XXXX-2</masked_card_number>
          <billing_address>`your value`</billing_address>
          <billing_address_2>`your value`</billing_address_2>
          <billing_city>`your value`</billing_city>
          <billing_state>`your value`</billing_state>
          <billing_zip>`your value`</billing_zip>
          <billing_country>`your value`</billing_country>
          <current_vault type="integer">`your value`</current_vault>
          <vault_token type="integer">`your value`</vault_token>
          <customer_vault_token>`your value`</customer_vault_token>
          <customer_id>`auto generated`</customer_id>
        </credit_card>
      </subscription>
      """

  Scenario: Update the product associated with the subscription
    Given I have a product family with ID "1502"
    And I have a product with these attributes
      | id   | handle | name       | price_in_cents | product_family_id |
      | 2001 | basic  | Basic Plan | 1900           | 1502              |
    And I have a product with these attributes
      | id   | handle | name       | price_in_cents | product_family_id |
      | 2002 | pro    | Pro Plan   | 9900           | 1502              |
    And I have an active subscription with ID "1000" to the product with handle "basic"
    And I have this xml subscription data
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <product_handle>pro</product_handle>
      </subscription>
      """
    When I send a PUT request with the xml data to https://acme.chargify.com/subscriptions/1000.xml
    Then the response status should be "200 OK"
    And the response should be the xml:
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <id type="integer">1000</id>
        <state>active</state>
        <previous_state>`auto generated`</previous_state>
        <balance_in_cents type="integer">0</balance_in_cents>
        <total_revenue_in_cents type="integer">`auto generated`</total_revenue_in_cents>
        <product_price_in_cents type="integer">`your value`</product_price_in_cents>
        <product_version_number type="integer">1</product_version_number>
        <current_period_started_at type="datetime">`auto generated`</current_period_started_at>
        <current_period_ends_at type="datetime">`auto generated`</current_period_ends_at>
        <next_assessment_at type="datetime">`auto generated`</next_assessment_at>
        <trial_started_at type="datetime">`auto generated`</trial_started_at>
        <trial_ended_at type="datetime">`auto generated`</trial_ended_at>
        <activated_at type="datetime">`auto generated`</activated_at>
        <expires_at type="datetime">`auto generated`</expires_at>
        <created_at type="datetime">`auto generated`</created_at>
        <updated_at type="datetime">`auto generated`</updated_at>
        <canceled_at type="datetime">`auto generated`</canceled_at>
        <cancellation_message nil="true"></cancellation_message>
        <cancel_at_end_of_period type="boolean">false</cancel_at_end_of_period>
        <delayed_cancel_at nil="true"></delayed_cancel_at>
        <coupon_code nil="true"></coupon_code>
        <signup_payment_id type="integer">`auto generated`</signup_payment_id>
        <signup_revenue>`your value`</signup_revenue>
        <payment_collection_method>automatic</payment_collection_method>
        <customer>
          <id type="integer">`auto generated`</id>
          <first_name>`your value`</first_name>
          <last_name>`your value`</last_name>
          <email>`your value`</email>
          <organization>`your value`</organization>
          <reference>`your value`</reference>
          <address>`your value`</address>
          <address_2>`your value`</address_2>
          <city>`your value`</city>
          <state>`your value`</state>
          <zip>`your value`</zip>
          <country>`your value`</country>
          <phone>`your value`</phone>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at>`auto generated`</updated_at>
        </customer>
        <product>
          <id type="integer">2002</id>
          <accounting_code>`your value`</accounting_code>
          <handle>pro</handle>
          <description>`your value`</description>
          <interval type="integer">`your value`</interval>
          <interval_unit>`your value`</interval_unit>
          <name>Pro Plan</name>
          <price_in_cents type="integer">9900</price_in_cents>
          <initial_charge_in_cents type="integer" nil="true"></initial_charge_in_cents>
          <trial_interval type="integer" nil="true"></trial_interval>
          <trial_interval_unit nil="true"></trial_interval_unit>
          <trial_price_in_cents type="integer" nil="true"></trial_price_in_cents>
          <expiration_interval type="integer">`your value`</expiration_interval>
          <expiration_interval_unit>`your value`</expiration_interval_unit>
          <archived_at type="datetime" nil="true"></archived_at>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at type="datetime">`auto generated`</updated_at>
          <request_credit_card type="boolean">true</request_credit_card>
          <require_credit_card type="boolean">true</require_credit_card>
          <return_url nil="true"></return_url>
          <update_return_url nil="true"></update_return_url>
          <return_params nil="true"></return_params>
          <product_family>
            <id type="integer">1502</id>
            <accounting_code>`your value`</accounting_code>
            <handle>`your value`</handle>
            <name>`your value`</name>
            <description>`your value`</description>
          </product_family>
        </product>
        <credit_card type="PaymentProfile">
          <id type="integer">`auto generated`</id>
          <card_type>`auto generated`</card_type>
          <expiration_month type="integer">`your value`</expiration_month>
          <expiration_year type="integer">`your value`</expiration_year>
          <first_name>`your value`</first_name>
          <last_name>`your value`</last_name>
          <masked_card_number>`your value`</masked_card_number>
          <billing_address>`your value`</billing_address>
          <billing_address_2>`your value`</billing_address_2>
          <billing_city>`your value`</billing_city>
          <billing_state>`your value`</billing_state>
          <billing_zip>`your value`</billing_zip>
          <billing_country>`your value`</billing_country>
          <current_vault type="integer">`your value`</current_vault>
          <vault_token type="integer">`your value`</vault_token>
          <customer_vault_token>`your value`</customer_vault_token>
          <customer_id>`auto generated`</customer_id>
        </credit_card>
      </subscription>
      """

  Scenario: Manually setting the next billing date to a later date
    Given I have an active subscription with ID "1000"
    And I have this xml subscription data
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <next_billing_at>[@new_date = @subscription.current_period_ends_at + 1.week]</next_billing_at>
      </subscription>
      """
    When I send a PUT request with the xml data to https://acme.chargify.com/subscriptions/1000.xml
    Then the response status should be "200 OK"
    And the subscription's "current_period_ends_at" should be set to the new date
    And the subscription's "next_assessment_at" should be set to the new date

  Scenario: Manually setting the next billing date to an earlier date
    Given I have an active subscription with ID "1000"
    And I have this xml subscription data
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <next_billing_at>[@new_date = @subscription.current_period_ends_at - 1.week]</next_billing_at>
      </subscription>
      """
    When I send a PUT request with the xml data to https://acme.chargify.com/subscriptions/1000.xml
    Then the response status should be "200 OK"
    And the subscription's "current_period_ends_at" should be set to the new date
    And the subscription's "next_assessment_at" should be set to the new date

  Scenario: Manually setting the next billing date to a date in the past
    Given I have an active subscription with ID "1000"
    And I have this xml subscription data
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <next_billing_at>[@new_date = 1.week.ago]</next_billing_at>
      </subscription>
      """
    When I send a PUT request with the xml data to https://acme.chargify.com/subscriptions/1000.xml
    Then the response status should be "422 Unprocessable Entity"
    And the subscription's "current_period_ends_at" should not be set to the new date
    And the subscription's "next_assessment_at" should not be set to the new date
    And the response should be the xml:
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <errors>
        <error>Provided 'Next Billing' date must be in the future</error>
      </errors>
      """

  Scenario: Manually setting the next billing date, with trial
    Given I have an active subscription with ID "1000"
    And I the subscription is trialing
    And I have this xml subscription data
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <next_billing_at>[@new_date = @subscription.current_period_ends_at + 1.week]</next_billing_at>
      </subscription>
      """
    When I send a PUT request with the xml data to https://acme.chargify.com/subscriptions/1000.xml
    When I send a PUT request with the json data to https://acme.chargify.com/subscriptions/1000.json
    Then the response status should be "200 OK"
    And the subscription's "current_period_ends_at" should be set to the new date
    And the subscription's "next_assessment_at" should be set to the new date
    And the subscription's "trial_ended_at" should be set to the new date

JSON Update Usage Example


Feature: Chargify Subscriptions Edit/Update JSON API
  In order to integrate my app with Chargify
  As a developer
  I want to edit/update a subscription via the Chargify JSON API

  Background:
    Given I am a valid API user for site with subdomain "acme"
    And I send and accept json

  Scenario: Update the credit card information on a subscription using credit_card_attributes
    Given I have an active subscription with ID "1000"
    And I have this json subscription data
      """
      {"subscription":{
        "credit_card_attributes":{
          "full_number":"2",
          "expiration_month":"10",
          "expiration_year":"2030"
        }
      }}
      """
    When I send a PUT request with the json data to https://acme.chargify.com/subscriptions/1000.json
    Then the response status should be "200 OK"
    And the response should be the json:
      """
      {"subscription":{
        "id":1000,
        "state":"active",
        "previous_state":`auto generated`,
        "balance_in_cents":`auto generated`,
        "total_revenue_in_cents":`auto generated`,
        "product_price_in_cents": 1000,
        "product_version_number": 1,
        "current_period_started_at":`auto generated`,
        "current_period_ends_at":`auto generated`,
        "next_assessment_at":`auto generated`,
        "activated_at":`auto generated`,
        "trial_ended_at":`auto generated`,
        "trial_started_at":`auto generated`,
        "expires_at":`auto generated`,
        "created_at":`auto generated`,
        "updated_at":`auto generated`,
        "canceled_at":`your value`,
        "cancellation_message":null,
        "cancel_at_end_of_period":false,
        "delayed_cancel_at":null,
        "coupon_code":`your value`,
        "signup_payment_id":`auto generated`,
        "signup_revenue":`your value`,
        "payment_collection_method":"automatic",
        "customer":{
          "id":`auto generated`,
          "first_name":`your value`,
          "last_name":`your value`,
          "email":`your value`,
          "organization":`your value`,
          "reference":`your value`,
          "address":`your value`,
          "address_2":`your value`,
          "city":`your value`,
          "state":`auto generated`,
          "zip":`auto generated`,
          "country":`auto generated`,
          "phone":`auto generated`,
          "updated_at":`auto generated`,
          "created_at":`auto generated`
        },
        "product":{
          "id":`auto generated`,
          "name":`your value`,
          "handle":`your value`,
          "price_in_cents":`your value`,
          "accounting_code":`your value`,
          "description":`your value`,
          "interval":`your value`,
          "interval_unit":`your value`,
          "initial_charge_in_cents":null,
          "trial_price_in_cents":null,
          "trial_interval":null,
          "trial_interval_unit":null,
          "expiration_interval_unit":null,
          "expiration_interval":null,
          "return_url":null,
          "update_return_url":null,
          "return_params":null,
          "require_credit_card":true,
          "request_credit_card":true,
          "created_at":`auto generated`,
          "updated_at":`auto generated`,
          "archived_at":null,
          "product_family":{
            "id":`auto generated`,
            "name":`your value`,
            "handle":`your value`,
            "accounting_code":`your value`,
            "description":`your value`
          }
        },
        "credit_card":{
          "id":`auto generated`,
          "first_name":`your value`,
          "last_name":`your value`,
          "masked_card_number":"XXXX-XXXX-XXXX-2",
          "card_type":`auto generated`,
          "expiration_month":10,
          "expiration_year":2030,
          "billing_address":`your value`,
          "billing_address_2":`your value`,
          "billing_city":`your value`,
          "billing_state":`your value`,
          "billing_zip":`your value`,
          "billing_country":`your value`,
          "current_vault":`your value`,
          "vault_token":`your value`,
          "customer_vault_token":`your value`,
          "customer_id":`auto generated`
        }
      }}
      """

  Scenario: Update the product associated with the subscription
    Given I have a product family with ID "1502"
    And I have a product with these attributes
      | id   | handle | name       | price_in_cents | product_family_id |
      | 2001 | basic  | Basic Plan | 1900           | 1502              |
    And I have a product with these attributes
      | id   | handle | name       | price_in_cents | product_family_id |
      | 2002 | pro    | Pro Plan   | 9900           | 1502              |
    And I have an active subscription with ID "1000" to the product with handle "basic"
    And I have this json subscription data
      """
      {"subscription":{
        "product_handle": "pro"
      }}
      """
    When I send a PUT request with the json data to https://acme.chargify.com/subscriptions/1000.json
    Then the response status should be "200 OK"
    And the response should be the json:
      """
      {"subscription":{
        "id":1000,
        "state":"active",
        "previous_state":`auto generated`,
        "balance_in_cents":`auto generated`,
        "total_revenue_in_cents":`auto generated`,
        "product_price_in_cents": 9900,
        "product_version_number": 1,
        "current_period_started_at":`auto generated`,
        "current_period_ends_at":`auto generated`,
        "next_assessment_at":`auto generated`,
        "activated_at":`auto generated`,
        "trial_ended_at":`auto generated`,
        "trial_started_at":`auto generated`,
        "expires_at":`auto generated`,
        "created_at":`auto generated`,
        "updated_at":`auto generated`,
        "canceled_at":`your value`,
        "cancellation_message":null,
        "cancel_at_end_of_period":false,
        "delayed_cancel_at":null,
        "coupon_code":`your value`,
        "signup_payment_id":`auto generated`,
        "signup_revenue":`your value`,
        "payment_collection_method":"automatic",
        "customer":{
          "id":`auto generated`,
          "first_name":`your value`,
          "last_name":`your value`,
          "email":`your value`,
          "organization":`your value`,
          "reference":`your value`,
          "address":`your value`,
          "address_2":`your value`,
          "city":`your value`,
          "state":`auto generated`,
          "zip":`auto generated`,
          "country":`auto generated`,
          "phone":`auto generated`,
          "updated_at":`auto generated`,
          "created_at":`auto generated`
        },
        "product":{
          "id":2002,
          "name":"Pro Plan",
          "handle":"pro",
          "price_in_cents": 9900,
          "accounting_code": `your value`,
          "description":`your value`,
          "interval": `your value`,
          "interval_unit": `your value`,
          "initial_charge_in_cents":null,
          "trial_price_in_cents":null,
          "trial_interval":null,
          "trial_interval_unit":null,
          "expiration_interval_unit":null,
          "expiration_interval":null,
          "return_url":null,
          "update_return_url":null,
          "return_params":null,
          "require_credit_card":true,
          "request_credit_card":true,
          "created_at":`auto generated`,
          "updated_at":`auto generated`,
          "archived_at":null,
          "product_family":{
            "id": 1502,
            "name": `your value`,
            "handle": `your value`,
            "accounting_code": `your value`,
            "description":`your value`
          }
        },
        "credit_card":{
          "id":`auto generated`,
          "first_name":`your value`,
          "last_name":`your value`,
          "masked_card_number":`your value`,
          "card_type":`auto generated`,
          "expiration_month":`your value`,
          "expiration_year":`your value`,
          "billing_address":`your value`,
          "billing_address_2":`your value`,
          "billing_city":`your value`,
          "billing_state":`your value`,
          "billing_zip":`your value`,
          "billing_country":`your value`,
          "current_vault":`your value`,
          "vault_token":`your value`,
          "customer_vault_token":`your value`,
          "customer_id":`auto generated`
        }
      }}
      """

  Scenario: Manually setting the next billing date to a later date
    Given I have an active subscription with ID "1000"
    And I have this json subscription data
      """
      {"subscription":{
        "next_billing_at": "[@new_date = @subscription.current_period_ends_at + 1.week]"
      }}
      """
    When I send a PUT request with the json data to https://acme.chargify.com/subscriptions/1000.json
    Then the response status should be "200 OK"
    And the subscription's "current_period_ends_at" should be set to the new date
    And the subscription's "next_assessment_at" should be set to the new date
    And the subscription's "trial_ended_at" should be nil

  Scenario: Manually setting the next billing date to an earlier date
    Given I have an active subscription with ID "1000"
    And I have this json subscription data
      """
      {"subscription":{
        "next_billing_at": "[@new_date = @subscription.current_period_ends_at - 1.week]"
      }}
      """
    When I send a PUT request with the json data to https://acme.chargify.com/subscriptions/1000.json
    Then the response status should be "200 OK"
    And the subscription's "current_period_ends_at" should be set to the new date
    And the subscription's "next_assessment_at" should be set to the new date
    And the subscription's "trial_ended_at" should be nil

  Scenario: Manually setting the next billing date to a date in the past
    Given I have an active subscription with ID "1000"
    And I have this json subscription data
      """
      {"subscription":{
        "next_billing_at": "[@new_date =1.week.ago]"
      }}
      """
    When I send a PUT request with the json data to https://acme.chargify.com/subscriptions/1000.json
    Then the response status should be "422 Unprocessable Entity"
    And the subscription's "current_period_ends_at" should not be set to the new date
    And the subscription's "next_assessment_at" should not be set to the new date

  Scenario: Update the product associated with the subscription to a product on a different product family
    Given I have a customer named "John Doe"
    And I have a 3 tier product family named "Grasshopper"
    And I have a product family named "Foosballs"
    And I have a product named "Expensive Plan"
    And "John Doe" is subscribed to the "Medium Plan" with subscription ID "1000"
    And I have this json subscription data
      """
      {"subscription":{
        "product_id": "[@product.id]"
      }}
      """
    When I send a PUT request with the json data to https://acme.chargify.com/subscriptions/1000.json
    Then the response status should be "200 OK"
    And the subscription should be on the "Expensive plan"
    And the response should be the json:
    """
    {"subscription":{
      "id":1000,
      "state":"active",
      "previous_state":`auto generated`,
      "balance_in_cents":`auto generated`,
      "total_revenue_in_cents":`auto generated`,
      "product_price_in_cents": 1000,
      "product_version_number": 1,
      "current_period_started_at":`auto generated`,
      "current_period_ends_at":`auto generated`,
      "next_assessment_at":`auto generated`,
      "activated_at":`auto generated`,
      "trial_ended_at":`auto generated`,
      "trial_started_at":`auto generated`,
      "expires_at":`auto generated`,
      "created_at":`auto generated`,
      "updated_at":`auto generated`,
      "canceled_at":`your value`,
      "cancellation_message":null,
      "cancel_at_end_of_period":false,
      "delayed_cancel_at":null,
      "coupon_code":`your value`,
      "signup_payment_id":`auto generated`,
      "signup_revenue":`your value`,
      "payment_collection_method":"automatic",
      "customer":{
        "id":`auto generated`,
        "first_name":`your value`,
        "last_name":`your value`,
        "email":`your value`,
        "organization":`your value`,
        "reference":`your value`,
        "address":`your value`,
        "address_2":`your value`,
        "city":`your value`,
        "state":`auto generated`,
        "zip":`auto generated`,
        "country":`auto generated`,
        "phone":`auto generated`,
        "updated_at":`auto generated`,
        "created_at":`auto generated`
      },
      "product":{
        "id":[@product.id],
        "name":"Expensive Plan",
        "handle":"[@product.handle]",
        "price_in_cents":[@product.price_in_cents],
        "accounting_code":"[@product.accounting_code]",
        "description":`your value`,
        "interval":[@product.interval],
        "interval_unit":"[@product.interval_unit]",
        "initial_charge_in_cents":null,
        "trial_price_in_cents":null,
        "trial_interval":null,
        "trial_interval_unit":null,
        "expiration_interval_unit":null,
        "expiration_interval":null,
        "return_url":null,
        "update_return_url":null,
        "return_params":null,
        "require_credit_card":true,
        "request_credit_card":true,
        "created_at":`auto generated`,
        "updated_at":`auto generated`,
        "archived_at":null,
        "product_family":{
          "id":[@product.product_family.id],
          "name":"[@product.product_family.name]",
          "handle":"[@product.product_family.handle]",
          "accounting_code":"[@product.product_family.accounting_code]",
          "description":`your value`
        }
      },
      "credit_card":{
        "id":`auto generated`,
        "first_name":`your value`,
        "last_name":`your value`,
        "masked_card_number":`your value`,
        "card_type":`auto generated`,
        "expiration_month":`your value`,
        "expiration_year":`your value`,
        "billing_address":`your value`,
        "billing_address_2":`your value`,
        "billing_city":`your value`,
        "billing_state":`your value`,
        "billing_zip":`your value`,
        "billing_country":`your value`,
        "current_vault":`your value`,
        "vault_token":`your value`,
        "customer_vault_token":`your value`,
        "customer_id":`auto generated`
      }
    }}
    """

XML Delete/Cancel Usage Example


Feature: Chargify Subscriptions Cancel XML API
  In order integrate my app with Chargify
  As a developer
  I want to cancel a subscription via the Chargify XML API

  Background:
    Given I am a valid API user
    And I accept xml responses


  Scenario: Cancel a subscription without giving a reason/message
    Given I have an active subscription
    When I send a DELETE request to https://[@subdomain].chargify.com/subscriptions/[@subscription.id].xml
    Then the response status should be "200 OK"


  Scenario: Cancel a subscription while giving a reason/message
    Given I have an active subscription
    And I have this xml subscription data
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <cancellation_message>
          Canceling the subscription via the API
        </cancellation_message>
      </subscription>
      """
    When I send a DELETE request with the xml data to https://[@subdomain].chargify.com/subscriptions/[@subscription.id].xml
    Then the response status should be "200 OK"

JSON Delete/Cancel Usage Example


Feature: Chargify Subscriptions Cancel JSON API
  In order integrate my app with Chargify
  As a developer
  I want to cancel a subscription via the Chargify JSON API

  Background:
    Given I am a valid API user
    And I accept json responses


  Scenario: Cancel a subscription without giving a reason/message
    Given I have an active subscription
    When I send a DELETE request to https://[@subdomain].chargify.com/subscriptions/[@subscription.id].json
    Then the response status should be "200 OK"


  Scenario: Cancel a subscription while giving a reason/message
    Given I have an active subscription
    And I have this json subscription data
      """
      {
        'subscription': {
          'cancellation_message': 'Canceling the subscription via the API'
        }
      }
      """
    When I send a DELETE request with the json data to https://[@subdomain].chargify.com/subscriptions/[@subscription.id].json
    Then the response status should be "200 OK"

XML Delayed Cancel Usage Example


Feature: Chargify Subscriptions Delayed Cancel XML API
  In order integrate my app with Chargify
  As a developer
  I want to cancel a subscription at the end of it's current period via the Chargify XML API

  Background:
    Given I am a valid API user
    And I accept xml responses

  Scenario: Delay cancel a subscription while giving a reason/message
    Given I have an active subscription
    And I have this xml subscription data
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <cancel_at_end_of_period>1</cancel_at_end_of_period>
		<cancellation_message>
			Canceling the subscription at the end of the period via the API
		</cancellation_message>
      </subscription>
      """
    When I send a PUT request with the xml data to https://[@subdomain].chargify.com/subscriptions/[@subscription.id].xml
    Then the response status should be "200 OK"
		And the response should be the subscription output xml, with the `cancel_at_end_of_period` set to the same value.
	
  Scenario: Delay cancel a subscription while giving no reason/message
    Given I have an active subscription
    And I have this xml subscription data
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <cancel_at_end_of_period>1</cancel_at_end_of_period>
      </subscription>
      """
    When I send a PUT request with the xml data to https://[@subdomain].chargify.com/subscriptions/[@subscription.id].xml
    Then the response status should be "200 OK"
		And the response should be the subscription output xml, with the `cancel_at_end_of_period` set to the same value.
	

JSON Delayed Cancel Usage Example


Feature: Chargify Subscriptions Delayed Cancel JSON API
  In order integrate my app with Chargify
  As a developer
  I want to cancel a subscription at the end of the period via the Chargify JSON API

  Background:
    Given I am a valid API user
    And I accept json responses

  Scenario: Delay cancel a subscription while giving a reason/message
    Given I have an active subscription
    And I have this json subscription data
      """
      {
        'subscription': {
					'cancel_at_end_of_period': 1,
          'cancellation_message': 'Canceling the subscription via the API'
        }
      }
      """
    When I send a PUT request with the json data to https://[@subdomain].chargify.com/subscriptions/[@subscription.id].json
    Then the response status should be "200 OK"
		And the response should be the subscription output json, with the `cancel_at_end_of_period` set to the same value.
		
	Scenario: Delay cancel a subscription while giving no reason/message
    Given I have an active subscription
    And I have this json subscription data
      """
      {
        'subscription': {
					'cancel_at_end_of_period': 1
        }
      }
      """
    When I send a PUT request with the json data to https://[@subdomain].chargify.com/subscriptions/[@subscription.id].json
    Then the response status should be "200 OK"
		And the response should be the subscription output json, with the `cancel_at_end_of_period` set to the same value.
		

XML Reactivation Example


Feature: Reactivation
  In order to allow my customers to cancel and then return to their plans
  As a Seller
  I want the ability to reactivate a canceled subscription

  Background:
    Given I am a valid API user for site with subdomain "acme"
    And I send and accept xml

  Scenario: Reactivating a canceled subscription
    Given I have a canceled subscription with ID "1000"
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.xml
    Then the response status should be "200 OK"
    And the subscription should be active
    And the response should be the xml:
      """
      <?xml version="1.0" encoding="UTF-8"?>
      <subscription>
        <id type="integer">1000</id>
        <state>active</state>
        <previous_state>`auto generated`</previous_state>
        <balance_in_cents type="integer">0</balance_in_cents>
        <total_revenue_in_cents type="integer">`auto generated`</total_revenue_in_cents>
        <product_price_in_cents type="integer">`your value`</product_price_in_cents>
        <product_version_number type="integer">1</product_version_number>
        <current_period_started_at type="datetime">`auto generated`</current_period_started_at>
        <current_period_ends_at type="datetime">`auto generated`</current_period_ends_at>
        <next_assessment_at type="datetime">`auto generated`</next_assessment_at>
        <trial_started_at type="datetime">`auto generated`</trial_started_at>
        <trial_ended_at type="datetime">`auto generated`</trial_ended_at>
        <activated_at type="datetime">`auto generated`</activated_at>
        <expires_at type="datetime">`auto generated`</expires_at>
        <created_at type="datetime">`auto generated`</created_at>
        <updated_at type="datetime">`auto generated`</updated_at>
        <canceled_at type="datetime">`auto generated`</canceled_at>
        <cancellation_message nil="true"></cancellation_message>
        <cancel_at_end_of_period type="boolean">false</cancel_at_end_of_period>
        <delayed_cancel_at nil="true"></delayed_cancel_at>
        <coupon_code nil="true"></coupon_code>
        <signup_payment_id type="integer">`auto generated`</signup_payment_id>
        <signup_revenue>`your value`</signup_revenue>
        <payment_collection_method>automatic</payment_collection_method>
        <customer>
          <id type="integer">`auto generated`</id>
          <first_name>`your value`</first_name>
          <last_name>`your value`</last_name>
          <email>`your value`</email>
          <organization>`your value`</organization>
          <reference>`your value`</reference>
          <address>`your value`</address>
          <address_2>`your value`</address_2>
          <city>`your value`</city>
          <state>`your value`</state>
          <zip>`your value`</zip>
          <country>`your value`</country>
          <phone>`your value`</phone>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at>`auto generated`</updated_at>
        </customer>
        <product>
          <id>`auto generated`</id>
          <accounting_code>`your value`</accounting_code>
          <handle>`your value`</handle>
          <description>`your value`</description>
          <interval>`your value`</interval>
          <interval_unit>`your value`</interval_unit>
          <name>`your value`</name>
          <price_in_cents>`your value`</price_in_cents>
          <initial_charge_in_cents type="integer" nil="true"></initial_charge_in_cents>
          <trial_interval type="integer" nil="true"></trial_interval>
          <trial_interval_unit nil="true"></trial_interval_unit>
          <trial_price_in_cents type="integer" nil="true"></trial_price_in_cents>
          <expiration_interval type="integer">`your value`</expiration_interval>
          <expiration_interval_unit>`your value`</expiration_interval_unit>
          <archived_at type="datetime" nil="true"></archived_at>
          <created_at type="datetime">`auto generated`</created_at>
          <updated_at type="datetime">`auto generated`</updated_at>
          <request_credit_card type="boolean">true</request_credit_card>
          <require_credit_card type="boolean">true</require_credit_card>
          <return_url nil="true"></return_url>
          <update_return_url nil="true"></update_return_url>
          <return_params nil="true"></return_params>
          <product_family>
            <id>`auto generated`</id>
            <accounting_code>`your value`</accounting_code>
            <handle>`your value`</handle>
            <name>`your value`</name>
            <description>`your value`</description>
          </product_family>
        </product>
        <credit_card type="PaymentProfile">
          <id type="integer">`auto generated`</id>
          <card_type>`auto generated`</card_type>
          <expiration_month type="integer">`your value`</expiration_month>
          <expiration_year type="integer">`your value`</expiration_year>
          <first_name>`your value`</first_name>
          <last_name>`your value`</last_name>
          <masked_card_number>XXXX-XXXX-XXXX-1</masked_card_number>
          <billing_address>`your value`</billing_address>
          <billing_address_2>`your value`</billing_address_2>
          <billing_city>`your value`</billing_city>
          <billing_state>`your value`</billing_state>
          <billing_zip>`your value`</billing_zip>
          <billing_country>`your value`</billing_country>
          <current_vault type="integer">`your value`</current_vault>
          <vault_token type="integer">`your value`</vault_token>
          <customer_vault_token>`your value`</customer_vault_token>
          <customer_id>`auto generated`</customer_id>
        </credit_card>
      </subscription>
      """

  Scenario: Reactivating a canceled subscription with an invalid payment profile
    Given I have a canceled subscription with ID "1000"
    And the subscription has an invalid payment profile
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.xml
    Then the response status should be "422 Unprocessable Entity"
    And the subscription should be canceled
    And the response should be the xml:
    """
    <?xml version="1.0" encoding="UTF-8"?>
    <errors>
      <error>The credit card on file could not be charged.</error>
    </errors>
    """

  Scenario: Attempting to reactivate an already active subscription
    Given I have an active subscription with ID "1000"
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.xml
    Then the response status should be "422 Unprocessable Entity"
    And the subscription should be active
    And the response should be the xml:
    """
    <?xml version="1.0" encoding="UTF-8"?>
    <errors>
      <error>Cannot reactivate a subscription that is not marked "Canceled", "Unpaid", or "Trial Ended".</error>
    </errors>
    """

  Scenario: Reactivating a canceled subscription while preserving the balance
    Given I have a product with ID "2002" that costs $19
    And I have a canceled subscription with ID "1000" to the product with ID "2002"
    Then 1 charge should exist for $19
    And 1 payment should exist for $19
    When the subscription has a negative balance of "19"
    And I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.xml?preserve_balance=1
    Then the response status should be "200 OK"
    And 2 charges should exist for $19
    And 1 payments should exist for $19
    And the subscription should be active
    And the subscription balance should be zero

  Scenario: Reactivating a canceled subscription with a coupon
    Given I have a canceled subscription with ID "1000"
    And it has no current period defined
    And I have a coupon named "Early Bird"
    And the coupon is set to recur for 6 periods
    And the coupon code is "EARLYBIRD"
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.json?coupon_code=EARLYBIRD
    Then the response status should be "200 OK"
    And the subscription should be active
    And the subscription should have applied a coupon with code "EARLYBIRD"

  Scenario: Reactivating a canceled subscription with a trial, without the include_trial flag
    Given I have a canceled subscription with ID "1000"
    And the product associated with the subscription has a trial
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.xml
    Then the response status should be "200 OK"
    And the subscription should be active

  Scenario: Reactivating a canceled subscription with a trial, with the include_trial flag
    Given I have a canceled subscription with ID "1000"
    And the product associated with the subscription has a trial
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.xml?include_trial=1
    Then the response status should be "200 OK"
    And the subscription should be trialing

  Scenario: Reactivating a trial ended subscription
    Given I have a trial_ended subscription with ID "1000"
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.xml
    Then the response status should be "200 OK"
    And the subscription should be active

  Scenario: Reactivating a trial ended subscription, without the include_trial flag
    Given I have a trial_ended subscription with ID "1000"
    And the product associated with the subscription has a trial
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.xml
    Then the response status should be "200 OK"
    And the subscription should be active

  Scenario: Reactivating a trial ended subscription, with the include_trial flag
    Given I have a trial_ended subscription with ID "1000"
    And the product associated with the subscription has a trial
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.xml?include_trial=1
    Then the response status should be "200 OK"
    And the subscription should be trialing

JSON Reactivation Example


Feature: Reactivation
  In order to allow my customers to cancel and then return to their plans
  As a Seller
  I want the ability to reactivate a canceled subscription

  Background:
    Given I am a valid API user for site with subdomain "acme"
    And I send and accept json

  Scenario: Reactivating a canceled subscription
    Given I have a canceled subscription with ID "1000"
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.json
    Then the response status should be "200 OK"
    And the subscription should be active
    And the response should be the json:
      """
      {"subscription":{
        "id":1000,
        "state":"active",
        "previous_state":`auto generated`,
        "balance_in_cents":0,
        "total_revenue_in_cents":2000,
        "product_price_in_cents": 1000,
        "product_version_number": 1,
        "current_period_started_at":`auto generated`,
        "current_period_ends_at":`auto generated`,
        "next_assessment_at":`auto generated`,
        "activated_at":`auto generated`,
        "trial_ended_at":`auto generated`,
        "trial_started_at":`auto generated`,
        "expires_at":`auto generated`,
        "created_at":`auto generated`,
        "updated_at":`auto generated`,
        "canceled_at":`your value`,
        "cancellation_message":null,
        "cancel_at_end_of_period":false,
        "delayed_cancel_at":null,
        "coupon_code":`your value`,
        "signup_payment_id":`auto generated`,
        "signup_revenue":`your value`,
        "payment_collection_method":"automatic",
        "customer":{
          "id":`auto generated`,
          "first_name":`your value`,
          "last_name":`your value`,
          "email":`your value`,
          "organization":`your value`,
          "reference":`your value`,
          "address":`your value`,
          "address_2":`your value`,
          "city":`your value`,
          "state":`auto generated`,
          "zip":`auto generated`,
          "country":`auto generated`,
          "phone":`auto generated`,
          "updated_at":`auto generated`,
          "created_at":`auto generated`
        },
        "product":{
          "id":`auto generated`,
          "name":`your value`,
          "handle":`your value`,
          "price_in_cents":`your value`,
          "accounting_code":`your value`,
          "description":`your value`,
          "interval":`your value`,
          "interval_unit":`your value`,
          "initial_charge_in_cents":null,
          "trial_price_in_cents":null,
          "trial_interval":null,
          "trial_interval_unit":null,
          "expiration_interval_unit":null,
          "expiration_interval":null,
          "return_url":null,
          "update_return_url":null,
          "return_params":null,
          "require_credit_card":true,
          "request_credit_card":true,
          "created_at":`auto generated`,
          "updated_at":`auto generated`,
          "archived_at":null,
          "product_family":{
            "id":`auto generated`,
            "name":`your value`,
            "handle":`your value`,
            "accounting_code":`your value`,
            "description":`your value`
          }
        },
        "credit_card":{
          "id":`auto generated`,
          "first_name":`your value`,
          "last_name":`your value`,
          "masked_card_number":"XXXX-XXXX-XXXX-1",
          "card_type":`auto generated`,
          "expiration_month":`your value`,
          "expiration_year":`your value`,
          "billing_address":`your value`,
          "billing_address_2":`your value`,
          "billing_city":`your value`,
          "billing_state":`your value`,
          "billing_zip":`your value`,
          "billing_country":`your value`,
          "current_vault":`your value`,
          "vault_token":`your value`,
          "customer_vault_token":`your value`,
          "customer_id":`auto generated`
        }
      }}
      """

  Scenario: Reactivating a canceled subscription with an invalid payment profile
    Given I have a canceled subscription with ID "1000"
    And the subscription has an invalid payment profile
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.json
    Then the response status should be "422 Unprocessable Entity"
    And the subscription should be canceled
    And the response should be the json:
      """
      {
      "errors": ["The credit card on file could not be charged."]
      }
      """

  Scenario: Attempting to reactivate an already active subscription
    Given I have an active subscription with ID "1000"
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.json
    Then the response status should be "422 Unprocessable Entity"
    And the subscription should be active
    And the response should be the json:
      """
      {
      "errors": ["Cannot reactivate a subscription that is not marked \"Canceled\", \"Unpaid\", or \"Trial Ended\"."]
      }
      """

  Scenario: Reactivating a canceled subscription while preserving the balance
    Given I have a product with ID "2002" that costs $19
    And I have a canceled subscription with ID "1000" to the product with ID "2002"
    Then 1 charge should exist for $19
    And 1 payment should exist for $19
    When the subscription has a negative balance of "19"
    And I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.json?preserve_balance=1
    Then the response status should be "200 OK"
    And 2 charges should exist for $19
    And 1 payments should exist for $19
    And the subscription should be active
    And the subscription balance should be zero

  Scenario: Reactivating a canceled subscription with a coupon
    Given I have a canceled subscription with ID "1000"
    And it has no current period defined
    And I have a coupon named "Early Bird"
    And the coupon is set to recur for 6 periods
    And the coupon code is "EARLYBIRD"
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.json?coupon_code=EARLYBIRD
    Then the response status should be "200 OK"
    And the subscription should be active
    And the subscription should have applied a coupon with code "EARLYBIRD"

  Scenario: Reactivating a canceled subscription with a trial, without the include_trial flag
    Given I have a canceled subscription with ID "1000"
    And the product associated with the subscription has a trial
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.json
    Then the response status should be "200 OK"
    And the subscription should be active

  Scenario: Reactivating a canceled subscription with a trial, with the include_trial flag
    Given I have a canceled subscription with ID "1000"
    And the product associated with the subscription has a trial
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.json?include_trial=1
    Then the response status should be "200 OK"
    And the subscription should be trialing

  Scenario: Reactivating a trial ended subscription
    Given I have a trial_ended subscription with ID "1000"
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.json
    Then the response status should be "200 OK"
    And the subscription should be active

  Scenario: Reactivating a trial ended subscription, without the include_trial flag
    Given I have a trial_ended subscription with ID "1000"
    And the product associated with the subscription has a trial
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.json
    Then the response status should be "200 OK"
    And the subscription should be active

  Scenario: Reactivating a trial ended subscription, with the include_trial flag
    Given I have a trial_ended subscription with ID "1000"
    And the product associated with the subscription has a trial
    When I send a PUT request to https://acme.chargify.com/subscriptions/1000/reactivate.json?include_trial=1
    Then the response status should be "200 OK"
    And the subscription should be trialing

XML Reset Balance Example


Feature: Reset Subscription Balance
  In order to allow sellers to reset a customer's balance back to zero
  As a Seller
  I want the ability to reset a subscription

  Background:
    Given I am a valid API user
    And I send and accept xml

  Scenario: Resetting the balance on a subscription with a positive balance
    Given I have a subscription
    And the subscription has a positive balance
    When I send a PUT request to https://[@subdomain].chargify.com/subscriptions/[@subscription.id]/reset_balance.xml
    Then the response status should be "200 OK"
    And the subscription balance should be zero

JSON Reset Balance Example


Feature: Reset Subscription Balance
  In order to allow sellers to reset a customer's balance back to zero
  As a Seller
  I want the ability to reset a subscription

  Background:
    Given I am a valid API user
    And I send and accept json

  Scenario: Resetting the balance on a subscription with a positive balance
    Given I have a subscription
    And the subscription has a positive balance
    When I send a PUT request to https://[@subdomain].chargify.com/subscriptions/[@subscription.id]/reset_balance.json
    Then the response status should be "200 OK"
    And the subscription balance should be zero