Docs / Merchant guide
Importing subscribers
Migrating from Recharge or CSV with dry-run validation and safety guarantees.
The importer moves your existing subscribers into WallaB.AI™ from a CSV export — with a full dry-run review before a single row is committed.
Sources
- Recharge — upload the subscription export directly; columns are mapped automatically.
- Generic CSV — a documented template (downloadable from the Import page) that fits an export from any platform.
- Skio / Loop — selectable today, but direct column mapping is still being verified against real exports; until then rows from those files get a clear per-row message directing you to the generic template. Direct Skio/Loop mapping is coming.
Limits: files up to 10 MB and 5,000 rows per batch. Larger migrations split cleanly into several files — each is deduplicated against the others, so there is no penalty for splitting.
The generic CSV format
Start from the downloadable template (the Download our template link on the Import page) — it is a ready-to-fill file with the exact header row and one example row. Save it as UTF-8; a leading byte-order mark (BOM) is tolerated. The header row is required — columns are matched by name, not position, so extra columns you don't need are ignored rather than shifting the mapping.
One CSV row is one subscription (one product line). Every column the importer understands:
| Column | Required? | Type | Format & constraints | Example |
|---|---|---|---|---|
customer_email | Required | string | The subscriber's email, name@example.com shape, up to 320 characters. Matched case-insensitively; an existing customer is reused, never duplicated. | shopper@example.com |
customer_first_name | Optional | string | Free text. Used only if the customer is new to your store. | Jane |
customer_last_name | Optional | string | Free text. Used only if the customer is new to your store. | Doe |
product_title | Required | string | Must match an ACTIVE product in your WallaB.AI catalog — paired with variant_title, or matched by variant_sku when that is supplied. | Colombian Dark Roast |
variant_title | Optional | string | Combined with product_title for the catalog match. Omit if you match by variant_sku. | 12oz Bag |
variant_sku | Optional | string | If present, matched case-insensitively against your catalog SKU and takes precedence over the title pair — the most reliable way to map a row. | COFFEE-DARK-12 |
quantity | Required | integer | A positive whole number, 1 to 999. | 1 |
unit_price | Required | decimal | A non-negative number using a dot decimal separator (no currency symbol or thousands separators). Rounded to 2 decimal places. | 18.00 |
currency | Optional | string | A 3-letter ISO currency code. Defaults to USD when blank; any non-USD value imports verbatim with a warning (sandbox billing is USD-denominated today). | USD |
interval_unit | Required | enum | One of day, week, or month (case-insensitive). Together with interval_count this is the billing cadence. | month |
interval_count | Required | integer | A positive whole number — e.g. 2 with interval_unit=week bills every two weeks. | 1 |
next_charge_date | Required | date | A calendar date, ISO 8601 (YYYY-MM-DD) recommended. Required for active and paused rows; optional for cancelled rows. A past date imports the row PAUSED — it is never charged for time already served. | 2026-08-01 |
status | Required | enum | One of active, paused, or cancelled (case-insensitive). A cancelled row imports as history for win-back, not an active subscription. | active |
source_subscription_id | Optional | string | Your source platform's stable subscription id. When present it is the dedup key; when blank, a fingerprint of the email, cadence, and line is used instead. Either way a re-import never creates a duplicate. | sub_10432 |
Deduplication
Each row carries a natural key: its source_subscription_id when you provide one, otherwise a fingerprint of the customer email, cadence, and line. At most one subscription is ever created per key — enforced by the database, not just app logic — so re-importing the same export changes nothing: matching rows are flagged and skipped, never duplicated and never used to overwrite the subscription that already exists. To edit an already-imported subscription, use the subscriber's page rather than re-uploading.
Validate first, commit second
Nothing touches your live data at upload time. Every row is staged and gets a verdict:
- valid — ready to import;
- warning — importable, but something is worth a look;
- error — will not import, with the exact reason (unknown product, malformed email, a subscription key that was already imported before, and so on).
You map each cadence in the file to one of your selling plans, review the verdict counts, and only then commit (owner-only). Committing enqueues the rows for processing; the batch report shows exactly what happened to each.
Safety guarantees
- No welcome emails. Imported subscribers never receive new-signup onboarding messages — nobody gets "welcomed" to a service they've been using for a year.
- No billing for time already served. A row whose next charge date is already in the past imports as paused, never as an overdue charge.
- No double imports. Each source subscription key is remembered; re-uploading the same export cannot create duplicates.
Migration incentive
Completing a migration batch earns you a one-time reward on your WallaB.AI plan — honored as account credit or an extended free trial under your current terms, arranged for you through Shopify (see Billing plans & support).