Subscription Contract Import Format
  • 31 May 2024
  • 35 Minutes to read
  • Contributors
  • Dark
    Light

Subscription Contract Import Format

  • Dark
    Light

Article summary

This section describes how to provide subscription contract data to the import service. A user can have multiple subscription contracts.

{
  "$ref": "#/definitions/subscriptionContractSchema",
  "definitions": {
    "subscriptionContractSchema": {
      "type": "object",
      "properties": {
        "subscriptionContracts": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "metadata": {
                "anyOf": [
                  {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "value": {
                          "type": ["string", "number", "boolean", "null"]
                        }
                      },
                      "required": ["key", "value"],
                      "additionalProperties": false
                    }
                  },
                  {
                    "type": "object",
                    "additionalProperties": {}
                  }
                ],
                "description": "A list of additional information to save about a subscription contract e.g [ { key: \"key\", value: \"value\" } ]"
              },
              "deliveryDetails": {
                "type": "object",
                "properties": {
                  "addressId": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The delivery address for the subscription, based on the ID with the Customer entity."
                  },
                  "adjustedDates": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "oldDate": {
                          "type": "string",
                          "format": "date",
                          "description": "The delivery date to adjust."
                        },
                        "newDate": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "date"
                            },
                            {
                              "type": "string",
                              "const": "POSTPONE"
                            }
                          ],
                          "description": "The new date to set the order on that date to, or the word POSTPONE, to shift all orders forward by one delivery interval."
                        }
                      },
                      "required": ["oldDate", "newDate"],
                      "additionalProperties": false
                    },
                    "description": "An array of date changes to optionally schedule for customers (e.g. if they already plan to postpone/prepone order). For most customers, this will likely be an empty array. Each date change will move one order only unless using the POSTPONE keyword."
                  },
                  "baseDate": {
                    "type": "string",
                    "format": "date",
                    "description": "The delivery date all future orders should be based on. For example, a date of 2023-01-01 in a monthly subscription would mean all future orders are sent on the first of the month. Normally this is the same date the subscription was set up, or when the delivery cadence was last updated."
                  },
                  "nextOrderOverride": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "orderOrdinal": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "playlistPosition": {
                            "type": "integer",
                            "minimum": 1
                          }
                        },
                        "required": ["orderOrdinal", "playlistPosition"],
                        "additionalProperties": false
                      },
                      {
                        "type": "null",
                        "description": "The order ordinal and playlist position to override the next order with."
                      }
                    ]
                  },
                  "previousOrder": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "deliveryDate": {
                            "type": "string",
                            "format": "date"
                          },
                          "orderOrdinal": {
                            "anyOf": [
                              {
                                "type": "array",
                                "items": {
                                  "type": "integer"
                                }
                              },
                              {
                                "type": "integer",
                                "minimum": 1
                              }
                            ],
                            "description": "The total number of orders the customer has received so far of a subscription contract, including the most recent. This should increment with refunded but not cancelled orders, and must match the total committed orders for the subscription in the orders export."
                          },
                          "playlistPosition": {
                            "anyOf": [
                              {
                                "type": "array",
                                "items": {
                                  "type": "integer"
                                }
                              },
                              {
                                "type": "integer",
                                "minimum": 1
                              }
                            ],
                            "description": "What number of a subscription box's subscription type this customer's order was for, e.g. box 5 from a playlist of 10 options. This generally matches the orderOrdinal but doesn't have to, for example, if a subscription started halfway through a playlist."
                          }
                        },
                        "required": ["deliveryDate", "orderOrdinal", "playlistPosition"],
                        "additionalProperties": false
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Information relating to the last order a customer received, including the delivery date, order ordinal, and playlist position."
                  }
                },
                "required": ["addressId", "adjustedDates", "baseDate", "nextOrderOverride", "previousOrder"],
                "additionalProperties": false,
                "description": "An object containing information about the delivery of the subscription."
              },
              "status": {
                "type": "string",
                "enum": ["ACTIVE", "CANCELLED", "PAUSED", "ENDED", "SUSPENDED", "DEACTIVATED"],
                "description": "The status of the subscription contract, which can be one of: \nACTIVE - a subscription for which the customer is still receiving orders.\nCANCELLED - a subscription which has stopped because the user chose to cancel it.\nPAUSED - a subscription which has stopped because the user chose to pause it. This is functionally the same as cancelled, but many merchants differentiate between the two to read customer intent.\nENDED - a subscription which has stopped because it has reached a planned end.\nSUSPENDED - a subscription which has stopped because of a failed payment, and may reactivate if billing retries are successful. If you do not wish to record this data then setting to DEACTIVATED is fine.\nDEACTIVATED - a subscription which has stopped because the system or an admin deactivated it rather than the customer."
              },
              "createdAt": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date-time"
                  },
                  {
                    "type": "string",
                    "format": "date"
                  }
                ],
                "description": "The date the customer started their subscription."
              },
              "subscriptionTypeId": {
                "type": "string",
                "minLength": 1,
                "description": "An identifier matching the one used in Subscription Types import or the ID of the subscription type once created."
              },
              "credit": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": ["OrderCredit", "MonetaryCredit"],
                      "description": "The type of credit the user can choose from, including: \nOrderCredit - the number of free orders a customer has credited to their subscription.\nMonetaryCredit - the amount in cash the customer can apply against the value of their future orders."
                    },
                    "value": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "The amount of the given credit, e.g. number of free orders."
                    }
                  },
                  "required": ["type", "value"],
                  "additionalProperties": false
                },
                "minItems": 0,
                "maxItems": 2,
                "description": "An array containing information about the credit available to the subscription.Provide an empty array if none is present."
              },
              "phases": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "deliveryCadence": {
                      "type": "object",
                      "properties": {
                        "durationUnit": {
                          "type": "string",
                          "enum": ["DAY", "MONTH", "WEEK", "QUARTER", "YEAR"],
                          "description": "The unit of time used for the period."
                        },
                        "quantity": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 1000,
                          "description": "The number of duration units that make up this period of time."
                        }
                      },
                      "required": ["durationUnit", "quantity"],
                      "additionalProperties": false,
                      "description": "A list of cadences corresponding to the cadence options of the subscription contract subscription type. Each cadence here must be one of the allowed values in a subscription type cadence periods, in order of the steps making up a type delivery cadence options."
                    },
                    "id": {
                      "type": "string",
                      "minLength": 1,
                      "description": "The ID of the subscription phase matching the relevant phase in the Subscription Types import."
                    },
                    "billing": {
                      "type": "object",
                      "properties": {
                        "frequency": {
                          "type": "object",
                          "properties": {
                            "durationUnit": {
                              "type": "string",
                              "const": "EVERY_N_ORDER",
                              "description": "Currently the only allowed value is EVERY_N_ORDER, meaning billing frequency is only defined by how many orders at a time a customer chooses to pay/pre-pay for."
                            },
                            "quantity": {
                              "type": "integer",
                              "minimum": 1,
                              "description": "The number of orders at a time the customer pays for."
                            }
                          },
                          "required": ["durationUnit", "quantity"],
                          "additionalProperties": false
                        }
                      },
                      "required": ["frequency"],
                      "additionalProperties": false,
                      "description": "An object containing the billing information for the subscription contract."
                    },
                    "products": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "minLength": 1
                          },
                          "quantity": {
                            "type": "integer",
                            "minimum": 1
                          }
                        },
                        "required": ["id", "quantity"],
                        "additionalProperties": false
                      },
                      "description": "Products added to each order created based on this subscription contract."
                    }
                  },
                  "required": ["deliveryCadence", "id", "billing", "products"],
                  "additionalProperties": false,
                  "description": "The choices of customers selected in each Subscription Type phase."
                }
              },
              "paymentMethod": {
                "type": "object",
                "properties": {
                  "providerCustomerId": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The unique identifier for a customer used within the payment provider."
                  },
                  "source": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The payment provider name."
                  },
                  "token": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The token given by the payment provider for a customer."
                  }
                },
                "required": ["providerCustomerId", "source", "token"],
                "additionalProperties": false
              },
              "delegate": {
                "type": "object",
                "properties": {
                  "delegateName": {
                    "type": "string",
                    "enum": ["RECHARGE", "SHOPIFY", "CUSTOM"],
                    "description": "The name of the platform exporting from - use CUSTOM for a home build."
                  },
                  "delegateCustomerId": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The ID of the customer in the current platform."
                  },
                  "delegateSubscriptionId": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The ID of the customer subscription in the existing platform."
                  }
                },
                "required": ["delegateName", "delegateCustomerId", "delegateSubscriptionId"],
                "additionalProperties": false,
                "description": "An object containing information about the current vendor used for the subscription."
              },
              "discounts": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string",
                      "minLength": 1,
                      "description": "The discount code to apply to the subscription contract, matching one from the Promotions data."
                    },
                    "addedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time"
                        },
                        {
                          "type": "string",
                          "format": "date"
                        }
                      ],
                      "description": "The date the discount code was added.This is used to determine which orders the code should have applied to, to count uses so far."
                    },
                    "orderOrdinals": {
                      "type": "array",
                      "items": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "description": "Specific order numbers to apply the discount to. If left blank, it will be applied to all future orders up to the termination criteria."
                    },
                    "terminationCriteria": {
                      "type": "object",
                      "properties": {
                        "orderOrdinal": {
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": 1
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": ["orderOrdinal"],
                      "additionalProperties": false,
                      "description": "The order ordinal beyond which the discount code will no longer be applied, can be null if the code is permanent. This is generally the sum of the previous order number and the promotion's remaining uses"
                    }
                  },
                  "required": ["code", "addedAt"],
                  "additionalProperties": false
                }
              },
              "customerId": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": [
              "metadata",
              "deliveryDetails",
              "status",
              "createdAt",
              "subscriptionTypeId",
              "credit",
              "phases",
              "paymentMethod",
              "delegate",
              "customerId"
            ],
            "additionalProperties": false
          },
          "minItems": 1
        }
      },
      "required": ["subscriptionContracts"],
      "additionalProperties": false,
      "description": "A list of subscription contracts used by customers"
    }
  },
  "$schema": "http://json-schema.org/draft-07/schema#"
}

Field Descriptions

  • createdAt - The date the customer started their subscription. The data model will be more accurate and powerful if this is the actual date the customer started their subscription rather than the date imported into Bento.

  • status - The status of the subscription contract, which can be one of:

    • ACTIVE - a subscription for which the customer is still receiving orders.

    • CANCELLED - a subscription which has stopped because the user chose to cancel it.

    • PAUSED - a subscription which has stopped because the user chose to pause it. This is functionally the same as cancelled, but many merchants differentiate between the two to read customer intent.

    • ENDED - a subscription which has stopped because it has reached a planned end.

    • SUSPENDED - a subscription which has stopped because of a failed payment, and may reactivate if billing retries are successful. If you don't wish to record this data then setting to DEACTIVATED is fine.

    • DEACTIVATED - a subscription which has stopped because the system or an admin deactivated it rather than the customer.

  • subscriptionTypeId - The ID of the subscription type. This must match the subscriptionTypeId provided in Subscription Types.

  • customerId - the unique identifier for a customer used within the platform. Must match that in Customers if using Bento's customer system.

  • phases: the choices of customers selected in each Subscripion Type phases

    • id: the ID of the subscription phase matching the relevant phase in the Subscription Types import.

    • deliveryCadence - A list of cadences corresponding to the cadence options of the subscription contract's subscription type. Each cadence here must be one of the allowed values in a subscription type's cadence periods, in order of the steps making up a type's delivery cadence options.

      • durationUnit - The unit of time used for the period. Can be one of: DAY, WEEK, MONTH, QUARTER, or YEAR.

      • quantity - The number of 'duration units' that make up this period of time.

    • billing - An object containing the billing information for the subscription contract.

      • frequency - The frequency of the subscription billing.

        • durationUnit - currently the only allowed value is EVERY_N_ORDER, meaning billing frequency is only defined by how many orders at a time a customer chooses to pay/pre-pay for.

        • quantity - The parameter for the durationUnit. For EVERY_N_ORDER, this means the number of orders at a time the customer pays for.

    • products - Products added to each order created based on this subscription contract.

      • id - The product id from the Product entity.

      • quantity - The quantity of the product to add to the order.

  • updatedAt - The date the customer's subscription was last updated, optional to add, and will default to the date when the customer is imported into Bento.

  • paymentMethod - The payment method used for subscription billing.

    • providerCustomerId - the unique identifier for a customer used within the payment provider.

    • paymentMethodToken - the token is given by the payment provider for a customer.

    • source - the payment provider name. We currently support BRAINTREE, STRIPE, and SHOPIFY (and our provider list is continuously expanding!).

  • credit - An array containing information about the credit available to the subscription. Provide an empty array if none is present.

    • type - the type of credit the user can choose from, including:

      • OrderCredit - the number of free orders a customer has credited to their subscription.

      • MonetaryCredit - the amount in cash the customer can apply against the value of their future orders.

    • value - the amount of the given credit, e.g. number of free orders.

  • delegate - An object containing information about the current vendor used for the subscription, e.g. Shopify or an in-house build.

    • delegateName, e.g. SHOPIFY, RECHARGE, CUSTOM.

    • delegateCustomerId - the ID of the customer in the current platform.

    • delegateSubscriptionId - the ID of the customer's subscription in the existing platform. This must match the IDs provided in data for the Orders import.

  • deliveryDetails - An object containing information about the delivery of the subscription.

    • addressId - Delivery address for the subscription, based on the id with the Customer entity.

    • baseDate - the delivery date all future orders should be based on. For example, a date of 2023-01-01 in a monthly subscription would mean all future orders are sent on the first of the month. Normally this is the same date the subscription was set up, or when the delivery cadence was last updated.

    • previousOrder - information relating to the last order a customer received

      • deliveryDate - When the last order was shipped.

      • orderOrdinal - The total number of orders the customer has received so far of a subscription contract, including the most recent. This must be equal to the sum of committed orders for this subscription contract in the orders export.

      • playlistPosition - What number of a subscription box's subscription type this customer's order was for, e.g. box 5 from a playlist of 10 options. This generally matches the orderOrdinal but doesn't have to, for example, if a subscription started halfway through a playlist.

    • adjustedDates - an array of date changes to optionally schedule for customers (e.g. if they already plan to postpone/prepone order). For most customers, this will likely be an empty array. Each date change will move one order only unless using the POSTPONE keyword.

      • oldDate - the delivery date to adjust.

      • newDate - the new date to set the order on that date to, or the word POSTPONE, to shift all orders forward by one delivery interval.

    • terminationCriteria - an optional field specifying what order number a subscription should finish on (e.g.for a 6 month gift subscription which the customer does not want to automatically roll on to an indefinite subscription).

      • orderOrdinal - the final order number in terms of total number of orders to be received for this subscription contract. This is generally the sum of the previous order number and the promotion’s remaining uses.

  • discounts - An array of promotion codes applied to the subscription. Provide an empty array if there are none.

    • code: The discount code to apply to the subscription contract.

    • addedAt: The date the discount code was added to the contract, used to work out whether the discount should apply to future orders.

    • terminationCriteria: The order ordinal beyond which the discount code will no longer be applied, can be null if the code is permanent.

      • orderOrdinal: the final order number in terms of total number of orders to be received this discount.

  • metadata - A list of additional information to save about a subscription contract.

    • key: the key of the metadata field.

    • value: the value of the metadata field.

Example

{
  "subscriptionContracts": [
    {
      "createdAt": "2020-07-23",
      "status": "ACTIVE",
      "subscriptionTypeId": "aaaaa-bbbbb-cccccc",
      "customerId": "aaaa-1111-zzzzz",
      "deliveryDetails": {
        "addressId": "random-address-id",
        "nextOrderOverride": null,
        "previousOrder": {
          "deliveryDate": "2024-02-21",
          "orderOrdinal": 1,
          "playlistPosition": 1
        },
        "adjustedDates": [
          {
            "oldDate": "2024-03-06",
            "newDate": "POSTPONE"
          }
        ],
        "baseDate": "2024-02-21"
      },
      "paymentMethod": {
        "source": "STRIPE",
        "token": "random-stripe-token"
      },
      "discounts": [
        {
          "code": "WELCOME-10-OFF",
          "addedAt": "2020-07-23",
          "terminationCriteria": {
            "orderOrdinal": 3
          }
        }
      ],
      "delegate": {
        "delegateName": "SHOPIFY",
        "delegateCustomerId": "111122223333",
        "delegateSubscriptionId": "44444555556666"
      },
      "metadata": [{"key": "key1", "value": "value1"}],
      "credit": [
        {
          "type": "OrderCredit",
          "value": 2
        }
      ],
      "phases": [
        {
          "id": "mmmmm11111-22222fffff-kkkkk888888",
          "deliveryCadence": {
            "durationUnit": "DAY",
            "quantity": 12
          },
          "billing": {
            "frequency": {
              "durationUnit": "EVERY_N_ORDER",
              "quantity": 1
            }
          },
          "products": [
            {
              "id": "a-dummy-product-id-1",
              "quantity": 3
            },
            {
              "id": "a-dummy-product-id-2",
              "quantity": 3
            }
          ]
        },
        {
          "id": "aaaa1111-ffff2222-hhhh9999",
          "deliveryCadence": {
            "durationUnit": "WEEK",
            "quantity": 4
          },
          "billing": {
            "frequency": {
              "durationUnit": "EVERY_N_ORDER",
              "quantity": 1
            }
          },
          "products": [
            {
              "id": "a-dummy-product-id-3",
              "quantity": 28
            }
          ]
        }
      ]
    }
  ]
}

Note: the billing interval will be the billing frequency multiplied by the delivery interval. For example if the billing frequency is 2 * EVERY_N_ORDER, and the delivery interval every 3 months, then they will be billed every 6 months.

In this example, the billing frequency will start off as weekly and move to monthly once the first cadence has expired.

Additional Requirements

  • The deliveryCadence field within each phase of a subscription contract must be one of the periods defined in a phase of Subscription Types. For example, if a subscription type has a single phase with delivery cadence options [{"duration": "MONTH", "values": [1]}], the delivery cadence of the subscription contract must be 1 month.

  • The billing field must match one of the options in the billing field of the subscription type's phase.

  • The products on a subscription contract must match those from the products specified in the matching subscription type phase.

  • The subscriptionTypeId field must match the provided ID in Subscription Types import data.

  • The customerId must match the ID provided in Customers import data (if providing).

  • The code for discounts must match a promotion code in the Promotions import data.

  • deliveryDetails.previousOrder.orderOrdinal must be the count of committed orders for the subscription in the Orders import data, matching the largest box number of a committed order in that file (so excluding cancelled orders which were never successfully billed).

FAQ

What does the discount termination criteria represent?

The orderOrdinal on terminationCriteria represents the final order number the discount should apply to, beginning from the start of that contract. So if the subscription has already had orders 1, 2, and 3 delivered, and then a promotion is applied to the contract for ORDER_NUMBER_AFTER_APPLIED 1, 2, and 3, then the terminationCriteria orderOrdinal for the subscription contract will be 6, because it needs to apply to 3 more orders.


Was this article helpful?