Check the complete list of parameters and responses of the POST customers migrate endpoint to do a migration.

const data = {
  customers: [
    {
      id: "your-id", // unique per account
      name: "John Smith",
      email: "john@smith.com", // unique per account
      registration_date: "1995-02-15T00:00:00.000Z",
      metrics: {  // optional - customer metrics for different time periods (lifetime, yearly, monthly, quarterly)
        lifetime: {
          to: "2025-02-21T14:05:42.164Z",
          from: "2024-11-27T17:57:13.756Z",
          tier_id: "8f26a2be-f922-4693-a273-9d7ab317024c",
          last_visit: "2024-12-10T20:58:01.965Z",
          spend_total: 50.2,
          number_of_purchases: 10
          },
        last_year: {
          to: "2025-01-01T07:59:59.999Z",
          from: "2024-01-01T08:00:00.000Z",
          tier_id: "142b1336-ef6e-40aa-be3f-33332003bfa5",
          last_visit: "2024-12-10T20:58:01.965Z",
          spend_total: 5.2,
          number_of_purchases: 3
        },
        this_year: {
          to: "2026-01-01T07:59:59.999Z",
          from: "2025-01-01T08:00:00.000Z",
          tier_id: "8f26a2be-f922-4693-a273-9d7ab317024c",
          last_visit: "2024-12-10T20:58:01.965Z",
          spend_total: 0,
          number_of_purchases: 0
        },
        last_month: {
          to: "2025-02-01T07:59:59.999Z",
          from: "2025-01-01T08:00:00.000Z",
          tier_id: "142b1336-ef6e-40aa-be3f-33332003bfa5",
          last_visit: "2024-12-10T20:58:01.965Z",
          spend_total: 10,
          number_of_purchases: 1
        },
        this_month: {
          to: "2025-03-01T07:59:59.999Z",
          from: "2025-02-01T08:00:00.000Z",
          tier_id: "8f26a2be-f922-4693-a273-9d7ab317024c",
          last_visit: "2024-12-10T20:58:01.965Z",
          spend_total: 0,
          number_of_purchases: 0
        },
        updated_at: "2025-02-21T14:05:42.164Z",
        last_quarter: {
          to: "2025-01-01T07:59:59.999Z",
          from: "2024-10-01T07:00:00.000Z",
          tier_id: "142b1336-ef6e-40aa-be3f-33332003bfa5",
          last_visit: "2024-12-10T20:58:01.965Z",
          spend_total: 0,
          number_of_purchases: 0
        },
        this_quarter: {
          to: "2025-04-01T06:59:59.999Z",
          from: "2025-01-01T08:00:00.000Z",
          tier_id: "8f26a2be-f922-4693-a273-9d7ab317024c",
          last_visit: "2024-12-10T20:58:01.965Z",
          spend_total: 0,
          number_of_purchases: 0
        },
        last_semester: {
          to: "2025-01-01T07:59:59.999Z",
          from: "2024-07-01T07:00:00.000Z",
          tier_id: "142b1336-ef6e-40aa-be3f-33332003bfa5",
          last_visit: "2024-12-10T20:58:01.965Z",
          spend_total: 10,
          number_of_purchases: 1
        },
        this_semester: {
          to: "2025-07-01T06:59:59.999Z",
          from: "2025-01-01T08:00:00.000Z",
          tier_id: "8f26a2be-f922-4693-a273-9d7ab317024c",
          last_visit: "2024-12-10T20:58:01.965Z",
          spend_total: 0,
          number_of_purchases: 0
        },
      },
      balance: [
        {
        amount: 2, // the amount of the balance item
        brand_id: null, // the id of the brand that owns the reward of this balance item.
        expiration_date: null, // the expiration date of the balance item
        reward_id: "b2bc86ad-5ccd-4fea-95fd-322a4a8f3f43",
        channel_id "e-commerce2", // optional, it has to already exist in your account
        funded_by: "marketing", // optional, who funded the rewards used in this balance item
        issued_at: "2025-01-05T00:00:00.000Z" // optional, the date when the balance item was originally issued. Defaults to right now.
        store_id: "cfc" // optional, it has to already exist in your account
       }
      ],
      devices: [
        {
          device_token: "fcm-token-123456789", // the unique token that identifies the device (given by firebase)
          device_info: {
            platform: "ios", // the platform of the device (ios, android, web, windows, macos)
            model: "iPhone 13", // the model of the device
            osVersion: "15.4" // the operating system version of the device
          },
          expires_at: "2025-12-31T23:59:59.999Z", // the date when the device token expires
          created_at: "2024-01-01T10:00:00.000Z" // the date when the device was registered
        }
      ]
    }
  ]
};

const response = await fetch("https://api.masivo.ai/customers/migrate", {
  method: "POST",
  headers: { Authorization: `Bearer ${accessToken}` },
  body: JSON.stringify(data)
});
You must not migrate deleted customers

Batch Processing

Customer migrations are handled in batches. You can include up to 1000 records per batch. Keep in mind that:

  • Batch Size: Ensure your migration payload does not exceed 1000 users.
  • Queuing: Migrations are not executed instantly; they are enqueued for processing. You may need to wait from a few seconds to a few minutes before the changes are visible in your dashboard, depending on how busy the queue is.

If you need to migrate several thousands o records, make sure you are in a Production account.

Prod account badged example

Migrate events

Why migrate events? Migrating events is useful when you want to bring along your customers’ behavior events such as purchases.

By default, all migrated events are marked as fulfilled and do not participate in active campaigns.

Unlike transactions, events can be migrated multiple times if you don’t have all of them available at once.

This section assumes you already had migrated your customers

Check the complete list of parameters and responses of the POST events migrate endpoint to perform a migration.

const data = {
  customers: [
    {
      id: "your-customer-id",
      events: [
        {
          brand_id: null, // the brand to which the reward belongs, null if the reward does not have a brand
          issued_at: "2025-01-30T17:50:19.423+00:00",
          resolved_at: "2025-01-30T17:50:19.423+00:00",
          type: "PURCHASE",
          fulfilled: true,
          // necessary for the metrics calculation
          order: {
            purchase_id: "1",
            value: 10,
            products: [
              {
                sku: "1",
                amount: 1,
                value: 1
              }
            ],
            payment_method: "CASH"
          }
        }
      ]
    }
  ]
};

const response = await fetch(
  "https://api.masivo.ai/api/storefront/v1/customers/migrate/events",
  {
    method: "POST",
    headers: { Authorization: `Bearer ${accessToken}` },
    body: JSON.stringify(data)
  }
);
You must not migrate reversed events

Batch Limits

  • The total number of events in the batch must not exceed 1000 and each customer must have at least one event.

Automatic Processing and Metrics

When events are migrated, the system automatically recalculates the customer’s metrics and updates their tier based solely on events with the PURCHASE type.

Migrate transactions

What is a transaction, and why is it important to migrate them? A transaction represents the history of accumulations and redemptions. Migrating transactions allows you to have a clear record that justifies the user’s previously migrated balance, providing a transparent explanation of why their wallet holds a specific amount.

For transactions to be processed successfully, they must match the customer’s balance. This is crucial to prevent any discrepancies or errors during the migration. Ensure that the transactions you are migrating align with the existing balance information of each customer.

This section assumes you already had migrated your customers and events

Check the complete list of parameters and responses of the POST transactions migrate endpoint to perform a migration.

const data = {
  customers: [
    {
      id: "your-customer-id",
      transactions: [
        {
          brand_id: null, // the brand to which the reward belongs
          reward_id: "ec9a5bfb-c2f1-4cf0-b509-247e47b96b65",
          details: "Migrated from old system", // details about this migrated transaction
          type: "ACCUMULATION",
          issued_at: "2025-01-30T17:50:19.423+00:00",
          resolved_at: "2025-01-30T17:50:19.423Z",
          cost: null,
          event: null,
          channel_id: null,
          store_id: null,
          amount: 4 // positive if it is ACCUMULATION type
        },
        {
          brand_id: null, // the brand to which the reward belongs
          reward_id: "ec9a5bfb-c2f1-4cf0-b509-247e47b96b65",
          details: "Migrated from old system", // details about this migrated transaction
          type: "REDEMPTION",
          issued_at: "2025-01-30T17:50:19.423+00:00",
          resolved_at: "2025-01-30T17:50:19.423Z",
          cost: null,
          event: null,
          channel_id: null,
          store_id: null,
          amount: -2 // negative if it REDEMPTION type
        }
      ]
    }
  ]
};

const response = await fetch(
  `https://api.masivo.ai/api/storefront/v1/customers/migrate/transactions`,
  {
    method: "POST",
    headers: { Authorization: `Bearer ${accessToken}` },
    body: JSON.stringify(data)
  }
);

Once transactions are migrated, you cannot migrate them again unless you first revert the customers’ migration. This ensures data integrity and prevents duplicate transactions.

Batch Limits

  • Ensure your migration payload does not exceed 1000 transactions.

Revert migration

Mistakes can happen during the migration process at any stage. To address this, we provide a solution through the revert customer migration endpoint.

Transactions and events cannot be reverted independently; instead, you must revert the entire customer migration. This ensures that all related data is automatically rolled back.

Important: Only migrated customers that have not produce a transaction can be reverted. This will also include all their related events and transactions.

Check the complete list of parameters and responses of the DEL revert migration endpoint to do a migration.

const data = {
  start_date: "2024-08-15T00:00:00.000Z", // migrated after
  end_date: "2025-05-15T00:00:00.000Z" // migrated before
};

const response = await fetch("https://api.masivo.ai/customers/migrate", {
  method: "DEL",
  headers: { Authorization: `Bearer ${accessToken}` },
  body: JSON.stringify(data)
});