Migrating to RecurrinGO!
Our support team runs your migration for you — you prepare the CSV, we validate and import it.
Step 1: Prepare your file
Export your subscription data as CSV, following the CSV format section below. Send it via the in-app chat on the Migration page (Settings → Migration).
Step 2: Dry run (validation only)
We run a dry run first — nothing is changed yet. We send back any rows with problems and why, typically within 1 hour if your CSV matches the required format.
Files with formatting issues may take longer, depending on the number of corrections needed.
What the dry run can and cannot catch. The dry run checks each row on its own: missing required fields, malformed dates, a bad gateway identifier, a PayPal ID that doesn't start with B-, an unsupported payment_gateway value. It does not contact Shopify for your data, so the following problems only surface during the real import:
rows of the same subscription not placed next to each other;
rows of the same subscription disagreeing on a subscription-level field (see Step 3 rules below);
a
variant_idthat doesn't exist in your store (or whose product can't be resolved);no matching Shopify customer, or an email matching more than one customer;
a customer with no saved payment method in Shopify (Scenario A);
the gateway rejecting or revoking the payment method (Scenario B).
Because of this, expect a second round of fixes after the real import on larger files — that is normal and safe: failed subscriptions are skipped, not half-created.
Step 3: Fix and resend
Correct the flagged rows and resend. We repeat validation until the file is clean.
Step 4: Real import
We run the live import. A row that fails validation, a group whose rows disagree, or an identifier we can't resolve skips that whole subscription — no half-built subscription is created from those. Rare infrastructure-level failures (a Shopify API error mid-build) are reported to you individually and re-run.
Step 5: Results
We send you a summary per subscription: imported / skipped / failed, with the reason for each failure. Reasons come from the import log, so every skipped subscription is traceable to a row number and a cause.
Good to know — re-runs:
Neither scenario deduplicates subscriptions. The import does not remember which subscriptions it already created, so re-importing a file that contains an already-migrated subscription creates a second subscription for that customer — and, once active, a second charge. A re-run must contain only the subscriptions that still need importing.
What is remembered in Scenario B is the payment method: a gateway reference that was already vaulted into Shopify is reused instead of being vaulted again. That makes a Scenario B re-run cheap and safe for payment methods, but it does not protect against duplicate subscriptions.
Using
status: PAUSEDon import is a useful safeguard while your old platform is still live, but it is not duplicate protection — see the post-migration checklist.
Common reasons a subscription fails: wrong/missing gateway identifier, a PayPal ID not starting with B-, no matching customer (and auto-create not enabled), an email matching more than one Shopify customer, the customer has no saved Shopify payment method (Scenario A), rows of the same subscription not adjacent or disagreeing on a subscription-level field, a variant_id that doesn't exist in the store, the gateway not yet chargeable (Stripe vault not transferred, PayPal not approved).
CSV File Format for Migration into RecurrinGO!
Before you start
Historical and analytics data is not migrated. Migrated customers and subscriptions will appear as new as of the migration date — past orders, analytics, and reporting history stay in your previous platform. Each migrated subscription gets exactly one placeholder order record (named
Imported) so cycle counting starts from 1.Bundle (box) and prepaid subscriptions aren't supported by this template yet. If you use these, contact support directly — since migration is handled manually by our team, these can still be migrated as an individual, custom case.
First, figure out which scenario you're in — it determines which columns you need.
Scenario A — Moving from another subscription app (Recharge, Bold, Appstle, etc.). Your customers and their payment methods are already in Shopify; only the subscriptions need to be rebuilt.
Scenario B — Moving from a payment gateway directly (Stripe, Braintree, Authorize.net, PayPal). Payment methods are still held by the gateway and need to be recreated inside Shopify as part of the import.
Rule of thumb: if you switched subscription apps but stayed on the same Shopify checkout, you're Scenario A. If you're bringing card/billing references out of Stripe/Braintree/Authorize.net/PayPal directly, you're Scenario B.
General file requirements (both scenarios):
CSV format, UTF-8 encoded, with a single header row.
One row = one product. A subscription with several products is several rows sharing the same
id, placed directly next to each other in the file.Subscription-level fields must be repeated, with identical values, on every row of the group. They are read from the first row, but the import compares them across all rows of the group and skips the whole subscription if any row disagrees — and a blank cell counts as a disagreement. Do not leave them empty on the 2nd and later rows.
The compared fields are:
customer_id,customer_email,next_billing_date,order_placed_date,status,final_amount,currency_code,delivery_price,is_auto_charging,payment_method_id,interval,interval_number,interval_type,shipping_address1,shipping_zip,shipping_country,shipping_country_code,shipping_province,shipping_province_code,billing_address1,payment_gateway,gateway_customer_id,gateway_payment_method_id.Simplest safe rule: fill every column on every row of the group, and vary only the per-line columns (
product_id,variant_id,quantity,final_price,requires_shipping).Products/variants referenced in the file must already exist in your Shopify store.
Additional prerequisites — Scenario A:
Each customer already exists as a Shopify customer.
Each customer has a saved payment method in Shopify (a specific one, or leave it blank to use their existing method automatically). If a customer has no saved method, that subscription can't be migrated this way.
Additional prerequisites — Scenario B:
Your store must be enabled for subscription migration by Shopify. This is a store-level permission on Shopify's side (not something the app can switch on); the import refuses to start without it. Request it from Shopify before sending the file — our team verifies it for you first.
The gateway is connected to your Shopify store and supports subscriptions.
Stripe only: if moving to Shopify Payments, your Stripe vault must first be transferred into the Shopify Payments Stripe account — request this from Stripe support directly. Until transferred, migrated Stripe methods aren't chargeable.
PayPal only: RecurrinGO! checks whether PayPal subscription support is enabled on your store before migrating — if it isn't, the migration won't go through. Your PayPal account also needs reference transactions approved (request from PayPal).
PayPal saved inside Braintree: export these as PayPal billing agreements and list them as PayPal rows — not as Braintree.
The RecurrinGO! app must have been re-opened/re-authorized after being granted permission to vault payment methods — our team will confirm this for you.
Billing address must be linked at the payment method level in the gateway before migration (Stripe, Braintree, Authorize.net). A missing billing address cannot be added or fixed after the migration — it must be verified and updated directly in the gateway beforehand. Note some gateways store billing address at both the customer level and the payment-method level; make sure it's present specifically on the payment method. PayPal is the exception: the
billing_…columns in the CSV are sent to Shopify as the billing agreement's address, so for PayPal rows you can supply it in the file.
Template headings explained
"Required" below means the import rejects the row without it. Several columns are formally optional but produce a silently wrong subscription when left blank — those are marked effectively required; see the defaults table after this section.
Column | Required? | Description |
| Required for multi-product subscriptions | Your subscription's ID from the old system. Groups rows belonging to the same subscription — keep them adjacent in the file. A single-product subscription can technically go without it, but always fill it: it's what our failure report points at. |
| Required (Scenario A) / one of | The customer's numeric Shopify ID. |
| Effectively required | Date of the next charge, e.g. |
| Required | Shopify variant ID (per row). Must exist in the store. |
| Optional | Shopify product ID (per row). If blank, it is resolved automatically from |
| Required (every row) | Shipping contact last name. |
| Required (every row) | Primary shipping address line. |
| Required (every row) | Shipping city. |
| Required (every row) | Shipping postal/ZIP code. |
| One required — fill both | Validation accepts either, but the stored subscription address only keeps the province when the name column is filled. Fill both to get a complete address in RecurrinGO! and in Shopify. |
| One required — fill both | Same as above: the stored address takes the country from the code column. Fill both. |
| Optional | Quantity of the line. Blank = 1. |
| Effectively required | Price per unit of the line. This is what Shopify actually charges. Blank = |
| Optional | Total that was charged per cycle in your old system. Recorded for reporting only — it does not set the charge amount. The amount actually charged is always |
| Always set explicitly |
|
| Optional | When the subscription originally started. Blank = today. |
| Effectively required | Billing frequency, e.g. |
| Effectively required | 3-letter currency code, e.g. |
| Optional | Shipping cost per cycle. Blank = 0 (free shipping). Charged on top of the line prices. |
| Required for auto-charge subscriptions (all of Scenario B) |
|
| Optional | Discount percentage applied to the whole subscription (read from the first row of the group — a different value on later rows is ignored). Blank = 0. |
| Optional | Whether the line ships physically (per row). |
| Optional | Additional shipping fields. |
| Optional | Billing name/address, if different from shipping. For PayPal, used as the billing agreement's address. |
What happens when an optional column is blank
There are no visible placeholders, but there are silent defaults. These are the ones that change money or timing:
Column | Blank means |
|
|
|
|
|
|
|
|
| every |
| paused (won't bill) |
| today |
| today |
| invoice subscription (no automatic charge) |
|
|
Payment columns
Scenario A — payments already in Shopify
Column | Required? | Description |
| Optional | The customer's Shopify saved payment method. Leave blank to use the customer's first available saved payment method (we warn you when a customer has more than one, so you can decide whether to name it explicitly). If none exist, the subscription fails to import. Only used for auto-charge subscriptions. |
Scenario B — payments in an external gateway
Column | Required? | Description |
| Required | One of |
| Required if | Used to identify the customer when you don't have their Shopify |
| Depends on gateway | The customer's ID within the gateway — see table below. |
| Depends on gateway | The payment method/token/agreement ID within the gateway — see table below. |
| Required — set | Without it the vaulted payment method is never charged (see the column table above). |
Leave payment_method_id blank for Scenario B — it's created automatically from the gateway reference.
Gateway |
|
|
Stripe | Customer ID | Payment method |
Braintree | Customer ID (Vault). Required. | Payment method token (Vault). Required. |
Customer profile ID (CIM). Required. | Payment profile ID (CIM). Required. | |
PayPal | Leave blank. | Billing Agreement ID starting with |
Supported payment providers: payment already in Shopify, Stripe, Braintree, Authorize.net, PayPal.
Note on timing: each new payment method is vaulted asynchronously by Shopify and the import waits for it (up to ~30 seconds per method). Large Scenario B files therefore take noticeably longer than Scenario A ones.
Additional columns
Optional — leave blank if they don't apply: product_id, quantity, order_placed_date, final_amount, delivery_price, subscription_discount_percent, requires_shipping, shipping_first_name/address2/phone/company, all billing_… fields.
Note that currency_code, final_price, interval*, status and is_auto_charging are technically optional but should always be filled — see the defaults table above.
Sample CSV file
Two examples, depending on your scenario:
migration-sample-scenario-a.csv — payments already in Shopify
⚠️ The product_id and variant_id values in these sample files are fictional placeholders used to illustrate the CSV structure — they are not real Shopify IDs and don't need to be swapped out; the point of the sample is the format, not the values. In your own file they must be real IDs from your store.
migration-sample-scenario-a.csv
migration-sample-scenario-b.csv — payments in: Stripe/Braintree/Authorize.net/PayPal
Note how the two rows of the multi-product subscription repeat every subscription-level value identically and differ only in the line columns.
Have questions about a migration? Message us from the Migration page in Settings, or reach out to support directly.
Post-migration checklist
Once your migration is complete, use this checklist to confirm everything came across correctly before cancelling your old platform. (This is a reference list, not a saved tracker — note articles like this one don't retain progress between visits, so keep track of it yourself if needed.)
Spot-check a sample of migrated subscriptions
Pick a handful of subscriptions (including at least one multi-product one) and open them in RecurrinGO!.
Confirm the products/variants, quantities, and prices match the original subscription — a
0.00price meansfinal_pricewas blank in the file.Confirm the next billing date is correct for each. Pay particular attention to subscriptions whose date was in the past in your file — those were moved forward automatically.
Confirm the currency is your store's currency, not
EUR.Confirm each subscription is the type you intended: auto-charge (charges the card) vs invoice (emails a payment link).
Confirm the shipping address is complete and correct, including state/province and country.
Confirm payment methods are valid
For Scenario A: confirm the correct saved payment method is attached (not just a method — the right one, especially for customers with multiple saved cards).
For Scenario B: confirm the gateway payment method was successfully converted into a working Shopify payment method (check the customer's record in Shopify).
Check the final report for any subscriptions marked failed or skipped, and follow up on each one individually.
Check for duplicates
If any file was imported more than once, check the affected customers for duplicate subscriptions — the import does not detect already-migrated subscriptions and will create a second one.
Double-check no subscription is active in both platforms at once for the same customer.
Activate migrated subscriptions safely
If you imported with
status: PAUSED, confirm your old platform is fully cancelled/deactivated before switching subscriptions to active in RecurrinGO!.Be aware that a customer can resume their own paused subscription from the customer portal. If the window between import and cancelling your old platform is long, tell support so we can keep the portal action out of reach until you're ready.
Wrap up
Cancel or deactivate the corresponding subscriptions in your previous platform.
Let your RecurrinGO! contact know the migration is confirmed and complete.
Migrations FAQ
Are my customers notified about the migration?
No notifications are sent by the import itself — customers are not emailed when their subscription is created. Note that once a migrated invoice subscription is active, the normal invoice email goes out on its next billing date; keep that in mind when choosing next_billing_date and status.
Are webhooks triggered during the import?
It depends on the subscription type. Auto-charge subscriptions create a real Shopify subscription contract, so subscription_contracts/create fires during the import. Invoice subscriptions don't create a Shopify contract and therefore trigger no webhook. If you use integrations (Klaviyo, analytics, etc.) that listen for subscription events, expect webhook activity for auto-charge subscriptions and plan accordingly.
Can my customers update their payment or billing info during the migration window?
Yes. After import, a subscription behaves like any other — including a paused one, which the customer can resume themselves from the portal. This has no effect on the import, which is already complete by the time the subscription is visible to the customer. If that's a risk for your rollout, tell support before the import.
What happens if a customer is missing data RecurrinGO! expects (e.g. no phone number)?
If required fields are missing (address line, city, ZIP, last name, country/region, variant), the subscription is not created. If optional fields are missing, the subscription — and the customer record if needed — is created without them. No visible placeholder text is inserted, but several blank fields fall back to a default value (currency EUR, price 0, frequency monthly, dates today, paused status) — see the defaults table in the CSV format section.
Is there a row limit for migration files?
There is no strict row limit. Very large files may take longer to process — Scenario B especially, since each new payment method is vaulted asynchronously by Shopify. If necessary, our team will split the file into batches manually. For most typical migrations, file size is not a concern.
Can I re-run a migration if I find a mistake after going live?
Yes, but the re-run file must contain only the subscriptions that still need importing. The import does not remember which subscriptions it already created, so a re-import of an already-migrated subscription produces a duplicate — in both scenarios. What Scenario B does remember is the payment method: an already-vaulted gateway reference is reused instead of being vaulted a second time.
Are bundle (box) or prepaid subscriptions supported?
Not yet via this template. Contact support directly — since migration is a manual, dev-assisted process, these can still be handled as an individual case.
Who do I contact if something looks wrong after migration?
Message us anytime from the Migration page in Settings (chat).