View migration file structure information

Ordergroove uses Migration Files to import in your existing customers, subscriptions, and products. In this guide, we'll discuss fields, formatting, and file structure. 

⚠️ Caution

Some aspects of this article may require technical expertise with coding languages. If you do not currently have someone on staff or contract that can provide that level of technical assistance, Ordergroove suggests seeking out that level of support before attempting to add or alter any working code relating to your subscriptions or storefront.


File Structure

Q: What kind of file is this?

It is a newline delimited JSON file where each customer's data is its own JSON object on its own line. When you open it up in a text editor, it should look something like this

blobid0.pngWhen we describe the fields later on in this document, we will use a pretty-format of one of these record lines because it is easier to understand and read.

But remember, one line is one JSON record.

 

Q: Why use a newline delimited JSON file?

It's the difference between reading a book on a single long page or breaking it up into 1000 pages.  With a newline delimited JSON file it is much faster to process one customer at a time.

 

Q: Is it one line per customer or subscription?

One line per customer. Addresses and payments and subscriptions are connected using their IDs in the origin object.

 

Q: Can I upload a 'prettified' version of the JSON file?

No, please use line-separated JSON.

 

Q: Which files should I be using with Ordergroove's migration tool?

After doing a test run or an import, always use the resulting files the system gives back to you as the "next version" of the records/file. Specifically: the Errors file will have context for partially created entities in the systems, which future runs will be able to take advantage of.

When doing a test run, you'll have two result files - a success file and an error file. You should modify the error file and retest it. You can then aggregate the success from that run with the previous run. Keep iterating like this until you are satisfied.

Any successful test run can be considered valid for importing. Similarly, after doing an import, you'll be given two result files a success file and an error file. The success file can be kept for accounting purposes, but the error file should be modified and then re-attempted for import. You can iterate on this process until you are satisfied with the results.


Row Structure

Q: What are the fields in a JSON record?

The customer record is made up of the following objects:

 The objects have cross references under the "origin" key which specifies the relationships they can have with one another.

 A Payment references 

  • an Address (billing address)

 A Subscription references

  • an Address (shipping address)
  • a Payment

Q: What are these other fields appearing in the JSON records after using Ordergroove's tools?

These are fields coming from Ordergroove. When you attempt an import of your data, some of these fields will be populated or changed in the output file.

Below is the top-level view of a record. The details of the objects omitted for clarity here; a full example of a record could be found at the bottom of this article.

{
  "customer": {
    // Customer object
  },
  "addresses": [
    {
      // Address object
    },
    ...
  ],
  "payments": [
    {
      // Payment object
    },
    ...
  ],
  "subscriptions": [
    {
      // Subscription object
    },
    ...
  ]
}

 

Customer object

This is what a fully expanded customer object will look like after it’s been run through our migration tools

{
  "customer": {
    "merchant": "aeafdd01234567890123456789001234",
    "merchant_user_id": "11112222334455",
    "first_name": "Sam",
    "last_name": "Smith",
    "email": "sam.smith.12345@emailservice.com",
    "live": true,
    "id": null,
    "merchant_id": null,
    "phone_number": "12223334444",
    "phone_type": null,
    "locale": null,
    "extra_data": null,
    "price_code": null,
    "created": null,
    "last_updated": null,
    "user_token_id": "",
    "session_id": "aeafdd01234567890123456789001234.11112222334455.12345678",
    "origin": {
      "id": "customer-0"
    }
  },
  ...
}

Some of the fields shown in the example sample data above will be automatically populated by our tooling. Please only populate the fields listed below.

Field name

Type

Notes

merchant

32 character string

Your program's unique ID within Ordergroove

merchant_user_id

string

EComm platform customer ID. This is the ID that your system and Ordergroove will use to represent a customer in your system.

first_name

string

 

last_name

string

 

email

string

 

live

boolean

Indicates if a customer has been deactivated

phone_number

string

Format: E.164

created

string

Format: YYYY-MM-DD HH:MM:SS

origin

JSON object

Customer identifier from the platform you're migrating from. May or may not be the same as the merchant_user_id

 

Address objects

The "addresses" key is an array comprised of one or many addresses that belong to the customer. There should be at least one shipping address and, if necessary, one billing address.

You can specify the address type using the "address_type" field. Here's an example of a single address within "addresses"

{
  ...
  "addresses": [
    {
        "customer": "11112222334455",
        "address_type": "shipping_address",
        "first_name": "Sam",
        "last_name": "Smith",
        "address": "12345 Main Street",
        "address2": null,
        "city": "New York",
        "state_province_code": "NY",
        "zip_postal_code": "10023",
        "country_code": "US",
        "live": true,
        "public_id": null,
        "label": null,
        "company_name": null,
        "phone": "12223334444",
        "fax": null,
        "created": null,
        "token_id": null,
        "store_public_id": null,
        "origin": {
          "id": "address-0"
        }
    },
    ...
  ],
}

Again, some of the fields shown in the example sample data above will be automatically populated by our tooling. Please only populate the fields listed below.

Field name

Type

Notes

customer

string

This contains the value from the merchant_user_id in the customer object (see above)

address_type

string

Options: “billing_address” or “shipping_address”

first_name

string

 

last_name

string

 

company_name

string

 

address

string

 

address2

string

 

city

string

 

state_province_code

string

State/province code. For your reference, you can examine the country and state codes we support.

zip_postal_code

string

Zip postal code

country_code

string

Two-letter country code. For your reference, you can examine the country and state codes we support.

phone

string

Format: E.164

live

boolean

Whether or not this address is still active and usable by the customer

origin

JSON object

Address identifier from the platform you're migrating from.

See example above.

 

Payment objects

The "payments" key is an array comprised of one or many payments that belong to the customer. There should be at least one payment which a customer's subscriptions are bound to.

Additionally, if the payment is bound to a billing address, you can use the origin.billing_address field on the Payment object to tell our tooling to look up the Address object of type "billing_address" with a matching origin.id value. If there is no billing address associated with the payment, you can omit this key/value pair.

{
  ...
  "payments": [
     {
        "customer": "11112222334455",
        "live": true,
        "token_id": "cus_ABCDEFG1234567",
        "billing_address": null,
        "public_id": null,
        "cc_number": "1111",
        "label": null,
        "cc_holder": null,
        "cc_type": 2,
        "cc_exp_date": "12/2030",
        "payment_method": "credit card",
        "created": null,
        "last_updated": null,
        "origin": {
          "id": "payment-0",
          "billing_address": "billing-0"
        }
     },
     ...
  ]
}

Again, some of the fields shown in the example sample data above will be automatically populated by our tooling. Please only populate the fields listed below.

Field name

Type

Notes

customer

string

This contains the value from the merchant_user_id in the customer object (see above)

cc_holder

string

Please check the requirements of your e-commerce store.


If this field is required outside of Ordergroove but not present in the data you migrate it could cause orders not to be placed down the line.

cc_type

integer

Options:

  • 1
    • Represents “Visa”
  • 2
    • Represents “MasterCard”
  • 3
    • Represents “American Express”
  • 4
    • Represents “Discover”
  • 5
    • Represents “Diners”
  • 6
    • Represents "JCB"

Please check the requirements of your e-commerce store.


If this field is required outside of Ordergroove but not present in the data you migrate it could cause orders not to be placed down the line.

payment_method

string

Can be "credit card", "paypal", "applepay", "shoppay", or "googlepay"

cc_exp_date

string

Format: MM/YYYY


Please check the requirements of your e-commerce store.


If this field is required outside of Ordergroove but not present in the data you migrate it could cause orders not to be placed down the line.

token_id

string

The payment reference your system can use to lookup and process recurring payments for the customer.

live

string

If the payment method is still active and usable by the customer

origin

JSON object

Contains a payment identifier from the platform you’re migrating from.


Also contains the billing reference, which is set on the “billing_address” field.


The “billing_address” value should correspond to an origin.id of a given Address object (see above).

 

Are you migrating to Shopify & Shopify Payments?

If needed, the Ordergroove migration system can import certain types of payment methods into Shopify Payments. Please reach out to Ordergroove for your specific payment migration needs. The following example is a record for migrating a Stripe payment to Shopify Payments when using the Stripe Legacy Gateway feature on Shopify:

{
  ...
  "payments": [
     {
        "customer": "11112222334455",
        "live": true,
        "token_id": "cus_ABCDEFG1234567",
        "billing_address": null,
        "public_id": null,
        "cc_number": "1111",
        "label": null,
        "cc_holder": null,
        "cc_type": 2,
        "cc_exp_date": "12/2030",
        "payment_method": "credit card",
        "created": null,
        "last_updated": null,
        "origin": {
          "id": "payment-0",
          "billing_address": "billing-0",
          "payment_processor": {
            "type": "stripe",
            "data": {
              "token": "cus_ABCDEFG1234567",
"stripe_payment_method_id": "..." } } } }, ... ] }

The origin object provides a “payment_processor” field which is where you can populate the data necessary to migrate your customer’s payment Shopify Payments. Here are the different payment types supported and their accompanying field requirements:

Stripe

{ 
...
"payment_processor": { "type": "stripe", "data": { "token": "STRIPE_CUSTOMER_TOKEN", "stripe_payment_method_id": "..." // Optional, but recommended to specify }
} }

Paypal

{
  ...
  "token_id": "PAYPAL_BILLING_AGREEMENT_ID", 
  "payment_method": "paypal",
  ...
  "origin": {
    ...
    "payment_processor": {
      "type": "paypal",
      "data": {
        "token": "PAYPAL_BILLING_AGREEMENT_ID"
      }
    }
  }
}

Auth.net - Note: Auth.net as a legacy subscription payment gateway is currently supported as a beta feature by Shopify. To use this feature, enable the legacy_subscriptions_authnet beta flag in your store. Please see this article for additional detail: https://shopify.dev/apps/subscriptions/migrate/customers#migrating-from-authorize-net

{ 
...
"payment_processor": { "type": "authorize", "data": { "token": "AUTH_NET_CUSTOMER_TOKEN", "customer_payment_profile_id": "..." // Optional, but recommended to specify }
}
}

Braintree - Note: Braintree as a legacy subscription payment gateway is currently supported as a beta feature by Shopify. To use this feature, enable the legacy_subscriptions_braintree beta flag in your store. Please see this article for additional detail: https://shopify.dev/apps/subscriptions/migrate/customers#migrating-from-braintree

{
  ...
  "payment_processor": {
    "type": "braintree",
    "data": {
      "token": "BT_CUSTOMER_TOKEN",
      "payment_method_token": "BT_PAYMENT_METHOD_TOKEN"
    }
  }
}

 

Subscription objects

The "subscriptions" key is an array comprised of one or many subscriptions that belong to the customer. The origin field really helps us here as it provides the origin.id references we should look for in a payment and shipping_address, respectively.

{
  …
  "subscriptions": [
    {
      "customer": "11112222334455",
      "product": "77889900556677",
      "offer": "eeff123412345678901234567890",
      "merchant_order_id": "rc_11112222334455_1234577",
      "live": true,
      "every": 30,
      "every_period": "day",
      "quantity": 2,
      "price": null,
      "payment": null,
      "shipping_address": null,
      "start_date": "2020-01-23",
      "cancelled": null,
      "cancel_reason": null,
      "cancel_reason_code": null,
      "next_order_date": "2022-08-15",
      "extra_data": null,
      "public_id": null,
      "session_id": "aeafdd01234567890123456789001234.11112222334455.12345678",
      "components": null,
"currency_code": "USD", "origin": { "id": "sub-0", "payment": "payment-0", "shipping_address": "shipping-0" }, … ] }

Again, some of the fields shown in the example sample data above will be automatically populated by our tooling. Please only populate the fields listed below.

Field name

Type

Notes

customer

string

This contains the value from the merchant_user_id in the customer object (see above)

start_date

string

The date when the subscription was created or the date it was most recently reactivated after having been canceled.

Format: YYYY-MM-DD

cancelled

string

The date when the subscription was most recently canceled

Format: YYYY-MM-DDThh:mm:ss

next_order_date

string

When we import this subscription this will be the date on which we create its next order.

Format: YYYY-MM-DD

live

boolean

Whether or not the subscription is active.

For 'Paused' subscriptions please use false.

merchant_order_id

string

The ID of the e-commerce order with which the subscription was originally created (when they enrolled).  This will be used to ensure accuracy and avoid duplicate subscriptions.

If you don’t have one, one suggested value is: <customer id>_<original subscription id>

product

string

The ID of the product in your e-commerce system.  Before you start the migration, this product's information must be included in the recurring product feed sent to Ordergroove. 

This is how we will identify the subscription product when placing orders.

every

integer

How often, in frequency periods, to send the subscription item. For example, if a subscription comes every four weeks this field would be "4"

every_period

string

Options: 

  • day
  • week
  • month

The frequency period to use when calculating the next order. 

For example, if a subscription comes every four weeks this field would be "week"

price

string

Should be set to null unless otherwise specified. Note that defining a price here does not influence the price customers will pay for a subscription item.

quantity

integer

How many units of the product the subscriber has subscribed to for each order.

offer

string

This will be provided to you when your account is created. It identifies the incentive profile for this subscription.

origin

JSON object

This contains the ID of the subscription from the platform your migrating from, along with the respective origin.id values from a shipping address and a payment

components

array of strings

An array of product IDs associated with the parent subscription product, often used for bundles.

Note: This is only used for Legacy Bundles. Use multi_item_bundle_components for the new Bundle Suite.

currency_code

string

The three letter ISO 4217 currency code of the subscription.


Prepaid subscription fields

Prepaid subscriptions have an additional field:

  • prepaid_subscription_context - A JSON object that contains information about prepaid subscriptions. Required if the subscription is prepaid.

This is an object containing information about prepaid subscriptions, and is only required if the subscription is prepaid. To use this field, you must have the prepaid feature flag enabled by Ordergroove. Otherwise, you will get errors during the migration process.

Example:

{
// other migration fields
"subscriptions": [
{
// other subscription fields
"prepaid_subscription_context": {
"prepaid_orders_remaining": 3,
"prepaid_orders_per_billing": 6,
"renewal_behavior": "autorenew"
}
}
]
}

There are three properties, all three are required. If errors are present, they will be returned in the `error` property of the `subscription`.

Property Type Notes
prepaid_orders_per_billing integer

The number of orders the customer prepays for at once. Must be an integer greater than 1.

prepaid_orders_remaining integer How many prepaid orders are left in the current billing cycle. Must be a positive integer or 0.
renewal_behavior string

What should happen at the end of a prepaid billing cycle. A strong with values:

  • 'autorenew' - after all prepaid orders have been placed, the next order will charge the customer for another `prepaid_orders_per_billing` orders
  • 'cancel' - the subscription will be canceled
  • 'downgrade' - the subscription will be downgraded to a pay-as-you-go subscription
  •  
{
// other migration fields
"subscriptions": [
{
// other subscription fields
"prepaid_subscription_context": {
"prepaid_orders_remaining": -1,
"prepaid_orders_per_billing": 6,
"renewal_behavior": "not_real"
},
"error": {
"prepaid_subscription_context": [
"Prepaid orders per billing should be an integer greater than 1",
"Prepaid orders remaining should be a non-negative integer",
"Renewal behavior should be one of: autorenew, cancel, downgrade"
]
}
}
],
"errors": ["Subscriptions validation errors"]
}

multi item bundle components

This is an array of each multi-item bundle component that makes up the subscription. This field is optional. To use this field, you must have the multi-item bundle feature flag enabled by Ordergroove. Otherwise, you will get errors during the migration process.

Note: This is only used for the New Bundle Suite. Use components for Legacy Bundles.

Example:

{
 // other migration fields
 "subscriptions": [
  {
     // other subscription fields
     "multi_item_bundle_components": [
      {
         "product": "123",
         "quantity": 1
      },
      {
         "product": "456",
         "quantity": 5
      }
    ]
  }
]
}

Both properties are required:

Property Type Notes
product string A string representing the `external_product_id` for the component.
quantity integer The total number of items in the bundle, must be positive.

 

Validations

In additional to validating the above properties are in the expected format, the migration process will also run the following checks:

  • Each subscription should not contain multiple components with the same product ID.
  • Each product should exist in Ordergroove's system.

If errors are present, they will be returned in the `error` property of the `subscription`.

{
 // other migration fields
 "subscriptions": [
  {
     // other subscription fields
     "multi_item_bundle_components": [
      {
         "product": "123",
         "quantity": 1
      },
      {
         "product": "456"
      },
      {
         "product": "789",
         "quantity": -1
      },
      {
         "product": 5555555,
         "quantity": 5
      }
    ],
     "error": {
       "multi_item_bundle_components": [
         "Product 456: Quantity is required",
         "Product 789: Quantity should be a positive integer",
         "Product 5555555: Product should be a string"
      ]
    }
  }
],
 "errors": ["Subscriptions validation errors"]
}

Example: one JSON record

You need to create the object below for each customer and put each object on a new line in a file

{
  "customer": {
    "merchant": "aeafdd01234567890123456789001234",
      "merchant_user_id": "11112222334455",
      "first_name": "Sam",
      "last_name": "Smith",
      "email": "sam.smith.12345@emailservice.com",
      "live": true,
      "id": null,
      "merchant_id": null,
      "phone_number": "12223334444",
      "phone_type": null,
      "locale": null,
      "extra_data": null,
      "price_code": null,
      "created": null,
      "last_updated": null,
      "user_token_id": "",
      "session_id": "aeafdd01234567890123456789001234.11112222334455.12345678",
      "origin": {
        "id": "customer-0"
      }
  },
  "addresses": [
    {
      "customer": "11112222334455",
      "address_type": "billing_address",
      "first_name": "Sam",
      "last_name": "Smith",
      "address": "12345 Main Street",
      "address2": null,
      "city": "New York",
      "state_province_code": "NY",
      "zip_postal_code": "10023",
      "country_code": "US",
      "live": true,
      "public_id": null,
      "label": null,
      "company_name": null,
      "phone": "12223334444",
      "fax": null,
      "created": null,
      "token_id": null,
      "store_public_id": null,
      "origin": {
        "id": "billing-0"
      }
    },
    {
      "customer": "11112222334455",
      "address_type": "shipping_address",
      "first_name": "Sam",
      "last_name": "Smith",
      "address": "12345 Main Street",
      "address2": null,
      "city": "New York",
      "state_province_code": "NY",
      "zip_postal_code": "10023",
      "country_code": "US",
      "live": true,
      "public_id": null,
      "label": null,
      "company_name": null,
      "phone": "12223334444",
      "fax": null,
      "created": null,
      "token_id": null,
      "store_public_id": null,
      "origin": {
        "id": "shipping-0"
      }
    }
  ],
  "payments": [
    {
      "customer": "11112222334455",
      "live": true,
      "token_id": "cus_ABCDEFG1234567",
      "billing_address": null,
      "public_id": null,
      "cc_number": "1111",
      "label": null,
      "cc_holder": null,
      "cc_type": 2,
      "cc_exp_date": "12/2030",
      "payment_method": "credit card",
      "created": null,
      "last_updated": null,
      "origin": {
        "id": "payment-0",
        "billing_address": "billing-0",
        "payment_processor": {
          "type": "stripe",
          "data": {
            "token": "cus_ABCDEFG1234567"
          }
        }
      }
    }
  ],
  "subscriptions": [
    {
      "customer": "11112222334455",
      "product": "77889900556677",
      "offer": "eeff123412345678901234567890",
      "merchant_order_id": "rc_11112222334455_1234577",
      "live": true,
      "every": 30,
      "every_period": "day",
      "quantity": 2,
      "price": null,
      "payment": null,
      "shipping_address": null,
      "start_date": "2020-01-23",
      "cancelled": null,
      "cancel_reason": null,
      "cancel_reason_code": null,
      "next_order_date": "2022-08-15",
      "extra_data": null,
      "public_id": null,
      "session_id": "aeafdd01234567890123456789001234.11112222334455.12345678",
      "components": null,
      "origin": {
        "id": "sub-0",
        "payment": "payment-0",
        "shipping_address": "shipping-0"
      }
    }
  ]
}

Example: Compacted record

{"customer":{"merchant":"aeafdd01234567890123456789001234","merchant_user_id":"11112222334455","first_name":"Sam","last_name":"Smith","email":"sam.smith.12345@emailservice.com","live":true,"id":null,"merchant_id":null,"phone_number":"12223334444","phone_type":null,"locale":null,"extra_data":null,"price_code":null,"created":null,"last_updated":null,"user_token_id":"","session_id":"aeafdd01234567890123456789001234.11112222334455.12345678","origin":{"id":"customer-0","address":"address-0"}},"addresses":[{"customer":"11112222334455","address_type":"shipping_address","first_name":"Sam","last_name":"Smith","address":"12345 Main Street","address2":null,"city":"New York","state_province_code":"NY","zip_postal_code":"10023","country_code":"US","live":true,"public_id":null,"label":null,"company_name":null,"phone":"12223334444","fax":null,"created":null,"token_id":null,"store_public_id":null,"origin":{"id":"address-0"}},{"customer":"11112222334455","address_type":"shipping_address","first_name":"Sam","last_name":"Smith","address":"12345 Main Street","address2":null,"city":"New York","state_province_code":"NY","zip_postal_code":"10023","country_code":"US","live":true,"public_id":null,"label":null,"company_name":null,"phone":"12223334444","fax":null,"created":null,"token_id":null,"store_public_id":null,"origin":{"id":"shipping-0"}}],"payments":[{"customer":"11112222334455","live":true,"token_id":"cus_ABCDEFG1234567","billing_address":null,"public_id":null,"cc_number":"1111","label":null,"cc_holder":null,"cc_type":2,"cc_exp_date":"12/2030","payment_method":"credit card","created":null,"last_updated":null,"origin":{"id":"payment-0","billing_address":"billing-0","payment_processor":{"type":"stripe","data":{"token":"cus_ABCDEFG1234567"}}}}],"subscriptions":[{"customer":"11112222334455","product":"77889900556677","offer":"eeff123412345678901234567890","merchant_order_id":"rc_11112222334455_1234577","live":true,"every":30,"every_period":"day","quantity":2,"price":"19.99","payment":null,"shipping_address":null,"start_date":"2020-01-23","cancelled":null,"cancel_reason":null,"cancel_reason_code":null,"next_order_date":"2022-08-15","extra_data":null,"public_id":null,"session_id":"aeafdd01234567890123456789001234.11112222334455.12345678","components":null,"origin":{"id":"sub-0","payment":"payment-0","shipping_address":"shipping-0"}}]}

Troubleshooting Errors

If you run into any errors during validation or import, Ordergroove will provide for you an error summary at the top level of the customer row object, along with more specific error details at the specific object's level. For a list of potential errors, details, and how to resolve them, take a look at Troubleshooting migration errors.