View migration file structure information

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”

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_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, 5=Diners
        "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

{
  ...
  "payment_method": "paypal",
  "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": "authnet", "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,
      "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 billing address and a payment

components

array of strings

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


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": 1,
"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": 1,
"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.

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"}}]}

Errors

In the case of any errors during validation or import, we'll 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 example

[
...
  {
    "customer": {...}
    },
    "addresses": [...],
    "payments": [
      {
        "customer": "11112222334455",
        "live": true,
        "token_id": null,
        "billing_address": null,
        "public_id": null,
        "cc_number": null,
        "label": null,
        "cc_holder": null,
        "cc_type": null,
        "cc_exp_date": null,
        "payment_method": "credit card",
        "created": null,
        "last_updated": null,
        "origin": {
          "id": "payment-0",
          "billing_address": "billing",
          "payment_processor": {
            "type": null,
            "data": {
              "token": null
            }
          }
        },
        "error": {
          "token_id": [
            "This field is required",
            "Expecting a string"
          ],
          "origin": [
            "unknown origin.payment_processor.type; expected stripe, paypal or authorize"
          ]
        }
      }
    ],
    "subscriptions": [...],
    "errors": [
      "Payment validation errors"
    ]
  }
]

Below you'll find most of the error messages you may find with those subscriptions that fail to import. Most of them are hopefully self-explanatory — however, we've provided an explanation where we think one could be needed. Error types include, but are not limited to

Customer object potential error messages

  • merchant_user_id: Expecting string
  • email: Missing @ sign
  • email: Multiple @ signs
  • email: Missing username
  • email: Domain needs to have a . sign in it
  • email: Empty string before "." in domain
  • email: Empty string after "." in domain

Address object potential error messages

  • address_type: Unsupported value. Expecting "shipping_address" or "billing_address"
    • Explanation: Your address object does not have a correctly formatted address type value
    • How To Resolve: use either "shipping_address" or "billing_address" as the field value
  • country_code: Given country code is not supported 
    • Explanation: You've provided an invalid country code or a country code to a country to which Ordergroove does not support shipping.  
    • How To Resolve: You can see all of the countries that we accept here in RC3 look through your dataset and ensure you're not trying to ship to countries not on that list or an invalid 2 letter ISO country code
  • state_province_code: Given state/province code for given country is not supported
    • Explanation: You've provided an invalid state code for a country.  
    • How To Resolve: We validate states using this data which is based on Google’s i18n address repository. Please check to ensure that the code provided matches what is in this data. 
  • phone: phone_number_validation_error - format is incorrect
    • Explanation: The phone number provided is either invalid or not in the correct format.
    • How To Resolve: Please ensure that all phone numbers are in E.164 formatting. Often this just involves dropping leading 0s and adding + symbol.

  • ReCharge Specific:
    • 'Untranslated country in billing address. Please change to 2 letter ISO code'
    • 'Untranslated state/province in billing address. '
    • 'Untranslated country in shipping address. Please change to 2 letter ISO code'
    • 'Untranslated state/province in shipping address. '
      • Explanation: The state and/or country code provided is either invalid or not in the correct format.
      • How To Resolve: We validate states using this data which is based on Google’s i18n address repository. Please check to ensure that the codes provided match what is in this data. 

Payment object potential error messages

  • cc_exp_date: Expecting string or null
    • How To Resolve: You can set this field to optional in RC3 or update your dataset and/or transformation process to ensure you're sending this value as a string or null (eg not an integer)
  • cc_exp_date: Expecting MM/YYYY date format
    • How To Resolve: You can set this field to optional in RC3 or update your dataset and/or transformation process to ensure you're sending this value in the expected format of MM/YYYY
  • token: Missing stripe customer token
    • Explanation: There is no stripe token for the payment method which is required to create a subscription using that payment method.
    • How To Resolve: If the payment method is not used - remove it.  Otherwise, you may need to look in Stripe's system or contact them (or ReCharge) directly

You may see the following error, in the context of an Errors after an attempted import

  • origin: Billing address does not exist 
    • Explanation: The ID of the billing address associated with this payment method has not been created and/or does not exist within the current customer's migration data.
    • How to resolve: double-check IDs and addresses in your system. If correct but you can't find the correct IDs provide your own IDs as long as they're sure to be unique and connect the billing address to the payment method correctly.

If you're migrating to Shopify payments...

When migrating to Shopify payments, you may encounter the following error message(s) in the origin

"payments": [
  ...
  {
    ...
    "origin": {
      "data": {
        ...
        "error": {
          "errorMessage": "[{\"code\":null,\"field\":null,\"message\":\"has already been taken\"}]",
          "getExistingPaymentError": "More than one payment already exist for customer. Cannot pick one"
        }
      }
    }
  }
]

This means that the provided payment token has already been migrated AND the customer has more than one payment in Shopify available to choose from. In order to provide a seemless a customer experience, we want to make sure that the correct payment the customer expects is associated with their subscription(s). With that in mind, our system makes no assumptions as to which Shopify payment should be used when more than one exists. If there's only one in Shopify, we use it.

How to resolve

  1. Log in to your Shopify store
  2. Find the customer and view their details

In the best case scenario, you'll see two payment methods that are identical. If that's the case then

  1. One can be deleted and the other cannot
  2. Delete the one
  3. Rerun the import with the data you have in the file
  4. If a customer only has one payment method, we'll use it during the import process

Otherwise, if you find that

  • Neither identical payment method can be deleted or
  • The payment methods are different

please open a ticket with us. We'll need you to tell us which payment method you want to use. This will allow us to  then be able to provide you with the Shopify payment token to populate the payment.token_id field with.

Subscription object potential error messages

  • price: Expecting string representing a decimal number
    • Explanation: In order to create a Shopify subscription contract you need to provide a price for the subscription.  This price will not be used when charging the customer and currently is inconsequential to the operation of the subscription.
    • How to resolve: Update the price on the subscription
  • next_order_date:  This is a required field for live subscriptions
    • Explanation: This is required for both Shopify Subscription Contract creation as well as the Ordergoove import
    • How to resolve:
  • next_order_date: Expecting date string with format YYYY-MM-DD
    • Explanation: You supplied a date but not in our required format
    • How to resolve: Please update this field to be in the following format: YYYY-MM-DD
  • next_order_date: Date is in the past
    • Explanation: We don't have a time machine xD. This happens sometimes if the file hasn't been updated recently.
    • How to resolve: Check your existing system to see what the next order date is currently.  If you've just done a dry run only -you can leave as is. If the error file was created during a live migration run you'll want to change the date in the error file to match the new date in your other system
  • start_date: Expecting date string with format YYYY-MM-DD
    • Explanation: You supplied a date but not in our required format
    • How to resolve: Please update this field to be in the following format: YYYY-MM-DD
  • canceled: Expecting date-time string with format YYYY-MM-DDThh:mm:ss
    • Explanation: You supplied a date but not in our required format
    • How to resolve: Please update this field to be in the following format: YYYY-MM-DDThh:mm:ss
  • origin: Shipping address does not exist
    • Explanation: The ID of the shipping address associated with this subscription has not been created and/or does not exist within the current customer's migration data.
    • How to resolve: double-check IDs and addresses in your system. If correct but you can't find the correct IDs provide your own IDs as long as they're sure to be unique and connect the shipping address to the subscription correctly.
  • origin: Payment does not exist
    • Explanation: The ID of the payment method associated with this subscription has not been created and/or does not exist within the current customer's migration data.
    • How to resolve: double-check IDs and addresses in your system. If correct but you can't find the correct IDs provide your own IDs as long as they're sure to be unique and connect the shipping address to the subscription correctly.

Subscriptions may also return an error that pertains to some precautions we have in place to ensure data is not duplicated over multiple runs of data. More specifically, we will flag if a customer has two subscription records with the same values for the following fields:

  • product
  • every
  • every_period
  • shipping_address
  • payment
  • merchant_order_id

When this happens, the error file will populate an error field on the subscription record with the following message:

400 Client Error: Bad Request for url: https://api.ordergroove.com/program_migrations/migrate_subscription - Subscription XXXXXX already exists with this information

Q: How do I determine if the subscription is legitimate or a duplicate?

Short of asking the customer, you should look at the customer record in the migration file and then look at the list of subscriptions.

In the simplest case, there's only one subscription object for the customer. This indicates that a retry mechanism was triggered in the import process but was retrying a failure on the client side that was successful on the server side.

If, however, you find one or more subscription objects in the customer row with matching fields as listed above, you'll need to determine if there was duplication during the extraction of the data or the construction of the data set.

If you find no such duplication occurred, please see below how to bypass our duplication check.

Q: How do I bypass the duplicate checks if the subscription is in fact legitimate?

If you determine that this is in fact legitimate, not a duplicate, and should be imported, then the recommended course of action is to modify the merchant_order_id field. Because it's a string, you can modify it any way you like.

Broader scope error messages

  • field: Expecting string
  • field: Whitespaces are not allowed

In some instances, there will be some network errors that occur during the migration. These will manifest with an error message indicating

  • Timeout occurred while making a request
  • Internal server error

For Timeout errors, you don't need to make any modifications to that particular object. Simply rerunning the import should be enough

If you see Internal server error, you can attempt to rerun the data as is, however, it is recommend that you please open a ticket with us if this error persists.

Comments

0 comments

Article is closed for comments.