> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hyperline.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Importing historical data

> Import customers, subscriptions, and invoices from another billing system

When migrating to Hyperline from another billing system, you can import your historical data using batch API endpoints. This allows you to maintain continuity in your billing records, reporting, and customer history.

<Info>
  **Dedicated import service available**

  This guide explains how to import historical data autonomously using our API. However, we also provide a dedicated service to help you migrate data from your existing billing system. If you'd prefer assistance with your migration, please contact us via the in-app chat or discuss this option with your sales contact.
</Info>

## What can be imported

You can import the following data types:

* **Customers**: Customer profiles with all associated metadata
* **Subscriptions**: Active and historical subscriptions with their configuration
* **Invoices**: Invoice records including PDF documents

## Prerequisites

Before importing subscriptions and invoices, you must configure your product catalog in Hyperline. Products referenced in subscription and invoice imports must already exist in your Hyperline account.

<Info>
  **Configure products first**

  Subscriptions and invoices might require valid Hyperline product identifiers in their import payloads. Create all necessary products in Hyperline before starting your data import, or the API will reject requests with unknown product references.
</Info>

You can create products through:

* The Hyperline web application under **Catalog > Products**
* The [Products API endpoints](/api-reference/endpoints/products/create-product)

## Import process overview

The recommended import sequence is:

1. Configure your product catalog (required for subscriptions and invoices)
2. Import customers (required for subscriptions and invoices)
3. Import subscriptions with historical start dates
4. Import invoices with their PDF documents

<Tip>
  **Test in sandbox first**

  Always test your import process in the sandbox environment before importing production data. This allows you to validate your data mapping and identify any issues without affecting live operations. Note that sandbox is not a clone of production — you'll need to seed it with a representative slice of customers and products to make the dry run meaningful.
</Tip>

## Importing customers

Use the batch customer creation endpoint to import multiple customers at once (up to 50 per request).

```sh theme={null}
curl -X POST https://api.hyperline.co/v1/customers/batch \
  -H "Authorization: Bearer <API key>" \
  -H "Content-Type: application/json" \
  -d '{
    "customers": [
      {
        "batch_customer_id": "batch_001",
        "name": "Acme Corporation",
        "billing_email": "billing@acme.com",
        "external_id": "cust_123_from_old_system"
      }
    ]
  }'
```

<Note>
  The `batch_customer_id` is required for batch operations to track each customer in the batch.
</Note>

<Tip>
  **Look up customers by your old IDs**

  Set the `external_id` field to your previous system's customer ID, and you can resolve customers later via the API without maintaining a separate mapping table:

  ```sh theme={null}
  GET /v1/customers?external_id=cust_123_from_old_system
  ```
</Tip>

For detailed parameters and response format, see the [Create customers batch](/api-reference/endpoints/customers/create-customers-batch) endpoint documentation.

## Importing subscriptions

Subscriptions can be created with start dates in the past, allowing you to preserve historical subscription data.

### Key considerations for subscription imports

* **Start date**: Set `starts_at` to the original subscription start date from your previous system
* **Initial billing date**: Set `initial_billing_at` to the first or next date when Hyperline should start billing. This should typically be the next renewal date or the date when you want Hyperline to take over billing operations
* **Activation strategy**: Use `start_date` to activate the subscription based on the `starts_at` date
* **Contract terms**: Define contract duration and renewal settings
* **Inactive subscriptions**: Import already-ended subscriptions only if you need them for historical reporting; otherwise skip them since they won't bill

```sh theme={null}
curl -X POST https://api.hyperline.co/v2/subscriptions \
  -H "Authorization: Bearer <API key>" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "cust_hyperline_id",
    "activation_strategy": "start_date",
    "starts_at": "2023-01-15T00:00:00Z",
    "initial_billing_at": "2026-02-15T00:00:00Z",
    "contract_terms": {
      "activation_strategy": "start_date",
      "end_strategy": "duration",
      "duration": {
        "period": "years",
        "count": 1
      },
      "renew_automatically": true
    },
    "products": [
      {
        "id": "prod_hyperline_id",
        "payment_interval": {
          "period": "years",
          "count": 1
        },
        "payment_schedule": "start"
      }
    ]
  }'
```

<Note>
  The product `id` must reference a product that already exists in your Hyperline product catalog. Map your old system's products to Hyperline product IDs before importing subscriptions.
</Note>

<Card title="Example 💡">
  A customer subscribed to your service on January 15, 2023, with annual billing. You're migrating to Hyperline in January 2026. Set `starts_at` to `2023-01-15` (preserving the original subscription start) and `initial_billing_at` to `2026-02-15` (the next renewal date when Hyperline should generate the invoice).
</Card>

For detailed parameters, see the [Create subscription](/api-reference/endpoints/subscriptions/create-subscription) endpoint documentation.

## Importing invoices

Import historical invoices to maintain complete billing records and enable accurate reporting.

### Batch invoice creation

Create multiple invoices at once (up to 50 per request):

```sh theme={null}
curl -X POST https://api.hyperline.co/v2/invoices/batch \
  -H "Authorization: Bearer <API key>" \
  -H "Content-Type: application/json" \
  -d '{
    "batch_id": "import_batch_2025_01",
    "invoices": [
      {
        "batch_invoice_id": "inv_123_from_old_system",
        "customer_id": "cust_hyperline_id",
        "status": "paid",
        "emitted_at": "2025-01-15T00:00:00Z",
        "due_at": "2025-02-15T00:00:00Z",
        "settled_at": "2025-01-20T00:00:00Z",
        "line_items": [
          {
            "product_id": "prod_hyperline_id",
            "name": "Annual subscription",
            "unit_amount": 12000,
            "units_count": 1
          }
        ]
      }
    ]
  }'
```

The endpoint returns a `202 Accepted` response with a `batch_id` that you can use to track the batch processing:

```json theme={null}
{
  "batch_id": "import_batch_2025_01"
}
```

<Note>
  The batch invoice creation endpoint processes invoices asynchronously — see [Tracking batch invoice creation](#tracking-batch-invoice-creation) below for the webhook events you can listen to. The `batch_invoice_id` is required to track each invoice in the batch. Each line item should reference a `product_id` from your product catalog. For paid invoices, include the `settled_at` date to record when payment was received.
</Note>

For detailed parameters, see the [Create invoices](/api-reference/endpoints/invoices/create-invoices) endpoint documentation.

### Tracking batch invoice creation

Since batch invoice creation is asynchronous, you should set up webhook listeners to track the success or failure of each invoice:

* **`invoice.batch.creation_succeeded`**: Triggered when an invoice in the batch is successfully created
* **`invoice.batch.creation_failed`**: Triggered when an invoice in the batch fails to be created

Each webhook event includes the `batch_id` and `batch_invoice_id` to help you track which invoices were processed successfully. See the [Webhooks documentation](/api-reference/docs/webhooks) for more details on setting up webhook endpoints.

### Importing invoice PDFs

After creating an invoice record, you can upload the original PDF document from your previous system:

```sh theme={null}
curl -X POST https://api.hyperline.co/v1/invoices/{invoice_id}/upload \
  -H "Authorization: Bearer <API key>" \
  -H "Content-Type: multipart/form-data" \
  -F "file=@/path/to/invoice.pdf"
```

This preserves the original invoice formatting and branding from your previous system, which can be important for customer records and compliance.

For detailed parameters, see the [Upload PDF to invoice](/api-reference/endpoints/invoices/upload-pdf-to-invoice) endpoint documentation.

## Best practices

### Data validation

* Validate all data before importing to ensure it meets Hyperline's requirements
* Check for required fields and data format compliance
* Test with a small batch first to identify any mapping issues

### Batch size management

* Process imports in batches of 50 items or fewer (API limit)
* Implement retry logic for failed batches
* Monitor API rate limits to avoid throttling

### Data mapping

* Create a mapping document between your old system's data structure and Hyperline's
* **Map products first**: Create a mapping between your old system's product IDs and Hyperline `product_id` values before importing subscriptions or invoices
* Use `external_id` and `metadata` fields to maintain references to original system IDs
* Document any data transformations or business logic applied during import

### Timing considerations

* Schedule imports during low-traffic periods to minimize impact
* Import customers before subscriptions and invoices (dependency order)
* Allow time for data validation and reconciliation after import

### Date and timezone handling

* All timestamps are interpreted as UTC — pass dates in ISO 8601 with an explicit offset (e.g. `2026-02-15T00:00:00Z`)
* A bare date or local-time string can shift the billing day by ±1 in customer-facing invoices when your timezone differs from UTC
* This matters most for `starts_at`, `initial_billing_at`, and the invoice `emitted_at` / `due_at` / `settled_at` fields — pick the same calendar day your old system used and append `T00:00:00Z`

### Reconciliation

After importing:

* Verify customer counts match between systems
* Reconcile subscription statuses and billing dates
* Confirm invoice totals and payment statuses
* Review reporting data to ensure accuracy

<Warning>
  **Irreversible operation**

  Data imports cannot be automatically reversed. Always test thoroughly in the sandbox environment before importing production data. Consider keeping backups of your original data until you've fully validated the import.
</Warning>
