Overview
Firmhouse supports two types of data imports:- Subscriptions Import - Import customer subscription records with their details, addresses, and billing information
- Ordered Products Import - Import products associated with subscriptions (requires subscriptions to be imported first)
;) separators. You can download empty templates directly from the import pages in the Firmhouse Portal.
Subscriptions Import
The subscriptions import allows you to migrate customer subscription data from your previous system. Each row in the CSV represents one subscription.Identification Fields
| Field | Required | Format | Description |
|---|---|---|---|
imported_subscription_id | Yes | String | The unique subscription identifier from your previous system. This prevents importing the same subscription twice and allows you to track which subscriptions have been migrated. Must be unique across all rows. |
imported_customer_id | No | String | The unique customer identifier from your previous system. Used for reference and tracking purposes, but not required for the migration to work. |
customer_id | No | String | The customer ID from Mollie payment provider, if you’re using Mollie for payments. This links the subscription to the customer record in Mollie’s system. Only needed if you’re migrating from a Mollie-based system. |
shopify_customer_id | No | String (gid://shopify/Customer/[digits]) | The Shopify customer ID if this subscription is linked to a Shopify customer. Used to sync customer data and orders between your subscription system and Shopify. |
stripe_customer_id | No | String | The Stripe customer ID if you’re using Stripe for payments. This links the subscription to the customer record in Stripe, allowing you to charge the customer through Stripe. |
Customer Details
| Field | Required | Format | Description |
|---|---|---|---|
email | Yes | Valid email address | The customer’s email address. This is used for account access, order confirmations, and all customer communications. Must be a valid email format. |
name | Yes | String | The customer’s first name. Used for personalization in communications and shipping labels. |
last_name | Yes | String | The customer’s last name. Used for personalization in communications and shipping labels. |
company_name | No | String | The company name if this is a business subscription. Leave empty for consumer subscriptions. |
phone_number | No | String | The customer’s phone number. Used for shipping notifications and customer support. Include country code if applicable. |
locale | Yes | nl, en, de, sv, fr, pl, fi, it, ro, es | The language preference for customer communications, emails, and the self-service portal. Determines which language version of emails and notifications the customer receives. |
marketing_opt_in | Yes | true, false | Whether the customer has consented to receive marketing emails and promotional communications. Set to ‘true’ if they opted in, ‘false’ if they opted out. Required for GDPR compliance. |
Shipping Address
| Field | Required | Format | Description |
|---|---|---|---|
address | Yes | String | The street address where products will be shipped. This is the primary shipping address for the subscription. |
house_number | No | String | The house or building number. Some countries require this to be separate from the street address for proper address validation. |
house_number_addition | No | String | Additional information for the address, such as apartment number, floor, or building unit. Examples: ‘A’, ‘2nd floor’, ‘Unit 5’. |
city | Yes | String | The city where the customer is located. Used for shipping calculations and address validation. |
zipcode | Yes | String | The postal or ZIP code. Format varies by country (e.g., ‘1234AB’ for Netherlands, ‘12345’ for US). Used for shipping and address validation. |
country | Yes | ISO 3166-1 alpha-2 code (e.g., NL, US, DE) | The country code where the customer is located. This affects shipping costs, tax calculations, and currency. |
Billing Address
All billing address fields are optional. Only fill these if the billing address is different from the shipping address. If left empty, the shipping address will be used for billing.| Field | Required | Format | Description |
|---|---|---|---|
bill_to_company_name | No | String | Company name for the billing address, if different from shipping address. |
bill_to_name | No | String | First name for the billing address. |
bill_to_last_name | No | String | Last name for the billing address. |
bill_to_address | No | String | Street address for billing. |
bill_to_house_number | No | String | House number for the billing address. |
bill_to_city | No | String | City for the billing address. |
bill_to_zipcode | No | String | Postal code for the billing address. |
bill_to_country | No | ISO 3166-1 alpha-2 code (e.g., NL, US, DE) | Country code for the billing address. |
Subscription Status and Dates
| Field | Required | Format | Description |
|---|---|---|---|
status | Yes | inactive, activated, paused, cancelled, stopped, one_time_purchase | The current state of the subscription. ‘activated’ means the customer is active and being billed. ‘paused’ means temporarily stopped but will resume. ‘cancelled’ or ‘stopped’ means permanently ended. ‘inactive’ means the subscription exists but hasn’t been activated yet. ‘one_time_purchase’ means a single purchase without recurring billing. |
signup_completed_at | Yes | YYYY-MM-DD HH:MM[+HH:MM] | When the customer completed the signup process. This is the timestamp when they finished registration, not when they first started. Used to track customer journey and calculate subscription age. |
activated_at | Yes | YYYY-MM-DD HH:MM[+HH:MM] | When the subscription became active and billing started. This is typically when the first payment was successful or when you manually activated the subscription. Used to calculate billing cycles and subscription duration. |
cancelled_at | No | YYYY-MM-DD HH:MM[+HH:MM] | When the subscription was cancelled. Fill this if the status is ‘cancelled’ or ‘stopped’. This date is used to determine when to stop billing and when access should end. |
stopped_at | No | YYYY-MM-DD HH:MM[+HH:MM] | When the subscription was stopped. Fill this if the status is ‘stopped’. Stopped subscriptions are permanently ended and cannot be reactivated, similar to cancelled subscriptions. |
paused_at | No | YYYY-MM-DD HH:MM[+HH:MM] | When the subscription was paused. Only fill this if the status is ‘paused’. Paused subscriptions temporarily stop billing but can be resumed later. |
paused_until | No | YYYY-MM-DD HH:MM[+HH:MM] | When a paused subscription should automatically resume. If set, the subscription will automatically reactivate on this date. Leave empty if the pause is indefinite. |
marked_as_non_paying_at | No | YYYY-MM-DD HH:MM[+HH:MM] | When the customer was marked as non-paying, typically due to payment failures. This helps track payment issues and may trigger dunning processes or account restrictions. |
Plan and Billing
| Field | Required | Format | Description |
|---|---|---|---|
next_billing_date | Yes | YYYY-MM-DD | The date when the next payment will be charged. This is calculated based on the billing cycle, but you can set it manually if needed. After each successful payment, this date automatically advances by the billing cycle interval. |
billing_cycle_interval | Yes | Integer | The numeric part of the billing frequency. Combined with billing_cycle_interval_unit, this determines how often the customer is charged. Example: if interval is ‘2’ and unit is ‘month’, customer is billed every 2 months. |
billing_cycle_interval_unit | Yes | day, week, month, year | The time unit for the billing cycle. Works together with billing_cycle_interval to define the billing frequency. For example, ‘1’ month means monthly billing, ‘2’ weeks means bi-weekly billing. |
shipping_costs_cents | No | Integer | Shipping costs in cents (not dollars/euros). For example, 500 means $5.00 or €5.00. Only needed if you’re importing Shopify subscriptions with custom shipping costs. Leave empty to use default shipping rates. |
Technical and Payment IDs
| Field | Required | Format | Description |
|---|---|---|---|
shopify_payment_method_id | No | gid://shopify/CustomerPaymentMethod/[32 lowercase alphanumeric chars] | The Shopify payment method ID (Global ID format). Only needed if this subscription is connected to Shopify and uses Shopify’s payment processing. This links to the saved payment method in Shopify. |
stripe_payment_method_id | No | String (e.g., pm_1234...) | The Stripe payment method ID. This is the saved payment method (card, bank account, etc.) that will be used for recurring charges. Only needed if using Stripe. |
stripe_mandate_id | No | String | The Stripe mandate ID for SEPA Direct Debit or other mandate-based payment methods. This is the authorization that allows you to charge the customer’s bank account. Only needed for SEPA or similar payment methods. |
Ordered Products Import
The ordered products import allows you to add products to subscriptions that have already been imported. Each row in the CSV represents one product line item on a subscription. Before importing ordered products, you must first import subscriptions using the Subscriptions Import.Subscription Reference
| Field | Required | Format | Description |
|---|---|---|---|
imported_subscription_id | Yes | String | The ID of the subscription from the original system. Must match a subscription that was previously imported via the Subscriptions import. |
Product Identification
You must provide at least one of the following product identifier fields. The system will use the first provided identifier to find the product.| Field | Required | Format | Description |
|---|---|---|---|
shopify_variant_id | No | gid://shopify/ProductVariant/[digits] | The Shopify variant ID (Global ID format) to identify the product. Use this if your product is synced from Shopify. |
product_id | No | Integer | The Firmhouse product ID (numeric) to identify the product. Use this if you know the internal product ID in Firmhouse. |
sku | No | String | The product SKU (Stock Keeping Unit) to identify the product. Use this if your products are identified by SKU. |
imported_product_id | No | String | The product ID from your original system. Use this if you’re migrating products and have mapped them using imported_product_id. |
Product Details
| Field | Required | Format | Description |
|---|---|---|---|
quantity | Yes | Integer | The quantity of the product to include in the subscription. This determines how many units of the product will be shipped per order. |
shipment_date | No | YYYY-MM-DD | The date when the next shipment should be sent. If not provided, the subscription’s next billing date will be used. |
interval | No | Integer | The numeric part of the shipment interval. Combined with interval_unit_of_measure, this determines how often the product is shipped. Example: if interval is ‘2’ and unit is ‘month’, product ships every 2 months. |
interval_unit_of_measure | No | default, day, week, month | The time unit for the shipment interval. Works together with interval to define shipping frequency. If not provided, defaults to the subscription’s billing cycle. |
custom_price_cents | No | Integer | A custom price override for this product in cents (not dollars/euros). For example, 500 means $5.00 or €5.00. If not provided, the product’s standard price will be used. |
Validation and Import Process
When you upload a CSV file, Firmhouse performs validation before any data is imported:- Format validation - The CSV file is checked for proper formatting and required columns
- Field validation - Each row is validated for required fields and correct data formats
- Reference validation - For ordered products, the system validates that referenced subscriptions exist
Tips for Successful Imports
- Download the empty CSV template from the import page to ensure you have all the correct column headers
- Use semicolons (
;) as field separators - Ensure all required fields are filled in for each row
- Use the correct date and time formats as specified
- For ordered products, make sure all referenced subscriptions have been imported first
- Review validation errors carefully and fix all issues before executing the import