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

# Add or deduct bonus in bulk

> Change many customers' bonus balances at once by importing a bonus adjustment file, then follow the import in the log.

This page helps you add bonus to many customers' balances, or take it away, in one go. You upload a file of adjustments on the **Data import** screen of Lobyco Nexus, and the **Import Log** shows how the import went.

> [!NOTE]
>
> You need access to **Data import**, under **System configuration** in the menu, or to **Bonus import**, under **Toolbox**. Bonus import is the same screen, for bonus adjustments only. If you see neither, ask your admin.

## Prepare the file

Your file has one row for each adjustment. Customers are called *members* in the file, so the customer's ID goes in `MemberId`.

| Column | Required | What it holds |
| - | - | - |
| `MemberId` | Yes | The ID of the customer whose balance you're changing. |
| `Amount` | Yes | The bonus to add. Use a negative amount to deduct bonus. |
| `StoreId` | Depends | The ID of a store the adjustment relates to. Some organisations need it on every row, and a row without it then fails. |
| `ReceiptId` | No | The ID of a receipt the adjustment relates to. |
| `Description` | Yes | Why you're changing the balance. It's for your records, and customers don't see it. |
| `FundedBy` | No | Who pays for the adjustment. It has to match one of the sponsors set up for your organisation. |
| `TransactionType` | Yes | The kind of transaction. It has to be one your organisation has set up, such as `BonusAdjustment` or `Adjustment`. |
| `ExpirationDate` | No | The day the bonus from this row runs out, written as yyyy-mm-dd. |

The import dialog shows the same list, apart from `ExpirationDate`. Choose **BonusAdjustment**, then select **See expected columns in file**.

A bonus runs out at the start of its `ExpirationDate`, not at the end. Lobyco takes it away in the first nightly run after midnight UTC on that date. So to let customers use the bonus up to and including 31 January, enter `2026-02-01`.

Save the file as a .csv file. The first row holds the column names, spelled as in the table. Separate the values with commas, and use a dot for decimals. A description that contains a comma goes in double quotes. You can leave out the optional columns you don't need.

> [!TIP]
>
> With some language settings, such as Danish or Swedish, Excel saves CSV files with semicolons and decimal commas. Open the file in a text editor, such as Notepad or TextEdit, to check that it uses commas and dots.

```csv theme={"system"}
MemberId,Amount,Description,TransactionType
100234,50,Apology for the app outage,BonusAdjustment
100871,-20.50,Bonus given twice by mistake,BonusAdjustment
```

A Product Bonus's product files use a different layout, shown on [Bonus types](/business-documentation/activities/bonuses/bonus-types#product-bonus).

If you choose **JSONL** when you import, save a .jsonl file instead, with one adjustment on each line.

## Import the file

> [!WARNING]
>
> Every import changes the balances again, even when it's the same file. Check the **Import Log** first, so you don't import a file twice.

1. In the menu, under **System configuration**, select **Data import**. If you have **Bonus import** instead, select it under **Toolbox**. The **Import Log** opens, with the imports made so far.
2. Select **Import new info**, at the top right.
3. In **Select which data to import**, choose **BonusAdjustment**.
4. Under **Select file format**, keep **CSV**, or choose **JSONL**.
5. Drag your file onto **Add file**, or choose **select file** to pick it.
6. Select **Import file**.

![The Import new info dialog of Data import, open over the Import Log. The dialog says that rows in the file with new IDs are added to the existing data, and rows with existing IDs replace the existing rows. Select which data to import shows BonusAdjustment. Under Select file format, CSV is selected and JSONL is not. Add file is an upload area that reads Drop file here to upload or select file, with Allowed file type is .csv under it. See expected columns in file is open and lists seven columns, with an asterisk on the required ones: MemberId (string, member identifier, required), Amount (decimal, the amount to add to the member's account, which can also be negative, required), StoreId (string, primary store identifier), ReceiptId (string, receipt identifier), Description (string, description of the adjustment, required), FundedBy (string, sponsor of the adjustment) and TransactionType (string, the type of transaction, for example BonusAdjustment or Adjustment, required). At the bottom are Cancel, and Import file, which is greyed out.](https://mintcdn.com/lobyco-4c9fb3ad/rG971_5ZfS49bcjM/images/bonuses-06-import-new-info-dialog.png?fit=max\&auto=format\&n=rG971_5ZfS49bcjM\&q=85\&s=06ba07dc1997f59940e398b19189f1a9)

*The Import new info dialog, with the expected columns open*

## Check the import

Your import appears in the **Import Log**, with its file name and your initials under **Imported by**. Its **Status** shows how it went.

* Select **Refresh** to update the list while the import runs.
* Select **View** on its row to see the details of the import.
* Select the download icon beside the file name to get a copy of the file you imported.

You can search and filter the log.

| Status | What it means |
| - | - |
| **Importing** | The file is still being processed. |
| **Successful** | Every row was imported, for example **Successful (200/200)**. |
| **Verification needed** | Some or all rows had errors. The status shows how many went through, for example **Verification needed (195/200)**. **Verification needed (0/200)** means none did. |
| **Failed** | The import stopped. Select **View** to see why. |

For **Successful** and **Verification needed**, check the number after the slash. It should match the number of rows in your file, not counting the header row. If it's lower, part of the file wasn't processed. Select **View** and look at the **Error type**.

* If it's `ChunkCreatingFailedEvent`, follow [Import the rows that were never read](#import-the-rows-that-were-never-read).
* If it's `ChunkImportIncomplete`, follow [Fix a failed import](#fix-a-failed-import).

## Get the rows that failed

When an import needs verification, these steps give you a file with only the rows that failed. You need it to fix the import, or to undo it.

1. Select **View** on the import's row. The details list each error, with its **Error type** and a **Description**.
2. If **View** shows a `TransactionCannotBeSaved` error, stop here, and don't fix or undo the import yourself. Some rows couldn't be saved. The error's **Description** asks you to retry the import, but don't. The index it gives can point to the wrong row. Contact Lobyco support with the file name and the date of the import.
3. Select **Download rows that requires verification**. You get a file named *Errors\_* plus your file's name, with the rows that failed.
4. If **View** shows an error about `TransactionType` or `FundedBy`, the file can hold the wrong rows. Delete any row that no error in **View** describes, because it went through. When a customer has more than one row, check that each row you keep has the problem its error describes. A `FundedByOptionsAreNotConfigured` error means every row with a `FundedBy` value failed.
5. If so, look in your own file for the rows with the `TransactionType` or `FundedBy` values those errors name. For a `FundedByOptionsAreNotConfigured` error, that's every row with a `FundedBy` value. Copy the missing ones into the *Errors\_* file.

The *Errors\_* file now holds only the rows that failed. Use it to [fix the import](#fix-an-import-that-needs-verification) or to [undo it](#undo-an-import).

## Fix an import that needs verification

The rows that went through are already on the customers' balances. So import only the rows that failed. The dialog suggests importing your corrected file again. If that file still holds the rows that went through, those customers get the change twice.

1. [Get the rows that failed](#get-the-rows-that-failed), in an *Errors\_* file.
2. Correct the rows you can. Delete the rows you can't fix, for example a customer with no active account.
3. Import the *Errors\_* file as a new import.

A row fails when:

* it has no `MemberId` or `Description`, or its `Amount` is 0
* its `TransactionType` isn't one your organisation has set up
* its `FundedBy` doesn't match one of your organisation's sponsors
* its `StoreId` is missing or unknown, in an organisation that needs one
* the customer has no active account
* a deduction would take the customer's balance below zero
* an addition would take the balance above the highest balance the customer's account allows

## Fix a failed import

Select **Refresh** first. A file the import couldn't read all the way through can show **Failed** before its first rows are imported. If it no longer shows **Failed**, follow [Check the import](#check-the-import) instead.

Select **View** on the import's row and look at the **Error type**.

* If it's `ChunkImportIncomplete`, the import stopped partway, and some rows may already be on the customers' balances. Don't import the file again. Contact Lobyco support.
* If it's only `ChunkCreatingFailedEvent`, the import couldn't read your file, and nothing was imported. Check that the file matches the format you chose and has rows below the header. In a CSV file, also delete any double quote inside a value, such as the one in `5" screen`. Keep the double quotes around a description that contains a comma. Then import the file again.
* Otherwise, nothing was imported. Check that the file has the columns above and matches the format you chose, then import it again.

If the file fails a second time, contact Lobyco support too. Whenever you contact Lobyco support about an import, give them the file name and the date of the import.

## Import the rows that were never read

When the number after the slash is lower than the number of rows in your file, and **View** shows a `ChunkCreatingFailedEvent` error, the import stopped reading your file partway. It read only the rows at the top, as many as the number after the slash. For example, **Successful (5000/5000)** for a file of 7,000 rows means it read the first 5,000. It never read the last 2,000.

1. Copy the rows it never read into a new file. In a CSV file, copy your header row above them.
2. If the new file is a CSV file, delete any double quote inside a value, such as the one in `5" screen`. It stops the import from reading the file. Keep the double quotes around a description that contains a comma.
3. Import the new file as a new import.

The new import's number after the slash then matches the number of rows in the new file, not counting the header row.

If the first import needed verification, fix its failed rows too, in [Fix an import that needs verification](#fix-an-import-that-needs-verification).

## Undo an import

To undo an import, import the rows that went through again, with each amount reversed.

1. If **View** shows a `ChunkImportIncomplete` error, follow [Fix a failed import](#fix-a-failed-import) instead.
2. If the import needed verification, [get the rows that failed](#get-the-rows-that-failed) first.
3. Make a copy of your file.
4. If **View** shows a `ChunkCreatingFailedEvent` error, the import read only the rows at the top of your file, as many as the number after the slash. Delete the rows below them from the copy.
5. If the import needed verification, remove the rows in your *Errors\_* file from the copy. They never went through.
6. Make the positive amounts negative, and the negative ones positive.
7. Import the copy as a new import.

A deduction can't take a customer's balance below zero. So a row fails for a customer who no longer has that much bonus, because they've spent it or it has expired.

## Related

* [Bonuses](/business-documentation/activities/bonuses) — how a bonus adjustment differs from a bonus activity.
* [Create a bonus](/business-documentation/activities/bonuses/create-a-bonus) — give customers extra bonus on their purchases while it runs, instead of a one-off change.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.