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

# Importing points

Importing points by file in the new points system works differently depending on if the Engage tenant is being configured *for the first time*, or if the Engage tenant is *already up and running*.

The folders where the files are placed have similar names, and these are easily confused, so take care to put them in right place depending on which of the two cases apply to you.

Each import is done by running a different scheduled job.

There is also a difference in how contacts are identified in the two imports.

The initial setup import will allow you to choose from a range of key types and keys (for example “memberNumber”), while in the ongoing points import you'll need to use the internal contact ID.

## Case 1 - When setting up tenant

Your CSV or XML file, formatted in the correct way, should be placed in this FTP folder:

```shell theme={null}
integration\pointTransactionImport
```

The job to run is `ImportHistoricalPointsFromFileJob` which will validate and import historical point files and store them in the database.

<Card title="How to import points history" href="/docs/file-based-transfer/historical-data/importing-historical-points" icon="https://mintcdn.com/voyado/Ns4bBcK3LNctK_Un/icons/developer-link.png?fit=max&auto=format&n=Ns4bBcK3LNctK_Un&q=85&s=fbd08f956358ab12f664a7158e1a1399" horizontal width="128" height="128" data-path="icons/developer-link.png" />

```csv Example with ValidTo theme={null}
Key;KeyType;PointDefinitionId;Amount;TransactionType;TransactionDate;CreatedOn;ValidTo;CreatedBy;Description;Source;ExpireAfterMonthsInactive
ABC123;MemberNumber;1;100.5;Purchase;2023-01-01T08:14:00.829Z;2023-01-01T08:14:00.829Z;2024-01-01T08:14:00.829Z;test@voyado.com;Test description;;
ABC123;MemberNumber;1;100;Purchase;2023-02-01T08:14:00.829Z;2023-02-01T08:14:00.829Z;2024-02-01T08:14:00.829Z;test@voyado.com;Test description1;;
ABC123;MemberNumber;1;-100;Return;2023-03-01T08:14:00.829Z;2023-03-01T08:14:00.829Z;2024-03-01T08:14:00.829Z;test@voyado.com;Test description2;;
```

```csv Example with ExpireAfterMonthsInactive theme={null}
Key;KeyType;PointDefinitionId;Amount;TransactionType;TransactionDate;CreatedOn;ValidTo;CreatedBy;Description;Source;ExpireAfterMonthsInactive
ABC123;MemberNumber;1;100.5;Purchase;2023-01-01T08:14:00.829Z;2023-01-01T08:14:00.829Z;;test@voyado.com;Test description;;12
ABC123;MemberNumber;1;100;Purchase;2023-02-01T08:14:00.829Z;2023-02-01T08:14:00.829Z;;test@voyado.com;Test description1;;12
ABC123;MemberNumber;1;-100;Return;2023-03-01T08:14:00.829Z;2023-03-01T08:14:00.829Z;;test@voyado.com;Test description2;;6
```

<Danger>
  The CSV file must always include both the `ValidTo` and `ExpireAfterMonthsInactive` columns. However, for each row, only *one* of these fields can contain a value. The unused field must be left empty, and not removed from the file.
</Danger>

For the setting-up case, it's important that no other point calculation are going on at the same time, such as points being added by API or automations. This import must be the only point job that is running. For the second job (see Case 2 below) it's not a problem to have several points calculations going at once.

<Warning>
  Always use . (a dot) for non-integer amounts in files. Using , (a comma) or anything else will cause an error. For example "10.50" is correct while "10,50" is not correct.
</Warning>

## Case 2 - When tenant is already active

When the tenant is already active, another job is used. This is a bit slower but more safe and ensures that no data is modified incorrectly.

Your CSV or XML file, formatted in the correct way, should be placed in this FTP folder:

```shell theme={null}
integration\pointTransaction
```

<Warning>
  CSV files in these imports should have a maximum of 2000 rows.
</Warning>

Multiple files can be imported in the same run.

The job to run is `ImportPointsFromFileJob` and this validates, reads and imports the points.

### Procedure

Create a file, and add it to the folder specified. Then run the scheduled job mentioned in the information. When the job runs it will handle all files added to the folder.

The import will add points in the same way as points are usually added in the system. To have the correct balance for point accounts after the import, the Update Balance job needs to run.

### Properties used

<ResponseField name="ContactId" type="guid">
  Must be an existing, not deleted, approved contact of type Member.
</ResponseField>

<ResponseField name="Amount" type="decimal">
  Cannot be 0.
</ResponseField>

<ResponseField name="DefinitionId" type="integer">
  Definition must exist in Engage.
</ResponseField>

<ResponseField name="TimeStamp" type="datetimeoffset">
  Can be NULL. Defaults to UTC Now Offset.
</ResponseField>

<ResponseField name="Source" type="string" required>
  Should not be empty. If points-based member levels are used, and you want to exclude some points, only use these predefined values:

  * Purchase
  * Adjustment
  * BonusBalanceAdjustment
  * Return
  * RewardVoucher
  * UpdateBalance
  * BonusPromotion
  * BonusPromotionReturn
  * Automation
</ResponseField>

<ResponseField name="Description" type="string">
  Should not be empty.
</ResponseField>

<ResponseField name="ValidFrom" type="datetimeoffset">
  Can be excluded from the file. Defaults to UTC Now Offset.
</ResponseField>

<ResponseField name="ValidTo" type="datetimeoffset">
  Can be excluded from the file. Defaults to the expiry rules set up for the tenant (for example, 12 months rolling expiry). Cannot be combined with a value in `ExpireAfterMonthsInactive`. One or the other may be used, or neither — never both in the same row.
</ResponseField>

<ResponseField name="ExpireAfterMonthsInactive" type="integer">
  Can be excluded from the file. Defaults to the expiry rules set up for the tenant (for example, “6” months). Must be higher than 0. Cannot be combined with a value in `ValidTo`. One or the other may be used or neither, but never both in the same row. Only to be used on active transactions. Transactions that have already expired must have an expiry date in `ValidTo` and no value in this field. Only applies if using the expiry method “Contact inactive”.
</ResponseField>

These settings currently only work with predefined legacy fields that can translate to the new predefined ones.

If the tenant setting for expiration is correctly set up AND the value of `validTo` or `expireAfterMonthsInactive` matches that expiration setting, these fields can both be set to blank and Engage will add the values based on what is set up in these expiration settings.

```csv Example with ValidTo theme={null}
ContactId;DefinitionId;Amount;ValidFrom;ValidTo;Description;Source;ExpireAfterMonthsInactive;TimeStamp
a20fe4f3-5cca-491f-ba2a-e6f04ff0d4d8;1;100.54;2023-01-01T08:14:00.829Z;2024-01-01T08:14:00.829Z;Test description;Purchase;;2023-01-01T08:14:00.829Z
db9b702c-9087-4c22-82a3-f133771a6c5f;1;100;2023-02-01T08:14:00.829Z;2024-02-01T08:14:00.829Z;Test description1;Adjustment;;2023-02-01T08:14:00.829Z
1dc891cb-ae93-492e-9d4d-aa985f3d781d;1;-100;2023-03-01T08:14:00.829Z;2024-03-01T08:14:00.829Z;Test description2;Return;;2023-03-01T08:14:00.829Z
```

```csv Example with ExpireAfterMonthsInactive theme={null}
ContactId;DefinitionId;Amount;ValidFrom;ValidTo;Description;Source;ExpireAfterMonthsInactive;TimeStamp
a20fe4f3-5cca-491f-ba2a-e6f04ff0d4d8;1;100.54;2023-01-01T08:14:00.829Z;;Test description;Purchase;12;2023-01-01T08:14:00.829Z
db9b702c-9087-4c22-82a3-f133771a6c5f;1;100;2023-02-01T08:14:00.829Z;;Test description1;Adjustment;12;2023-02-01T08:14:00.829Z
1dc891cb-ae93-492e-9d4d-aa985f3d781d;1;-100;2023-03-01T08:14:00.829Z;;Test description2;Return;6;2023-03-01T08:14:00.829Z
```

<Danger>
  The CSV file must always include both the `ValidTo` and `ExpireAfterMonthsInactive` columns. However, for each row, only *one* of these fields can contain a value. The unused field must be left empty, and not removed from the file.
</Danger>

## Validation errors

Here are the validations errors you might get and what they mean.

<AccordionGroup>
  <Accordion title="Missing Field Exception">
    *PointTransaction file import missing mandatory columns, will skip file: \[FileName]*\
    Here, the import file does not define all fields used. The file will be skipped and the error logged.
  </Accordion>

  <Accordion title="Missing Contact ID">
    *Missing contactId: \[contactId] In data that was not valid: \[\[notAccepted]]*\
    The contact ID used does not represent an existing, not-deleted and approved contact of type “Member”. The file line will be skipped and the error logged.
  </Accordion>

  <Accordion title="Missing Definition ID">
    *Missing PointDefinitionId: \[\[definitionIds]] In data that was not valid: \[\[notAccepted]]*\
    Definition ID does not have a corresponding point definition in the database. File line will be skipped and the error logged.
  </Accordion>

  <Accordion title="Source is empty">
    *Other error message: \[\[error]] In data that was not valid: \[\[notAccepted]]*\
    Source does not have a value. File line will be skipped and the error logged.
  </Accordion>

  <Accordion title="Description is empty">
    *Other error message: \[\[error]] In data that was not valid: \[\[notAccepted]]*\
    Description does not have a value. File line will be skipped and the error logged.
  </Accordion>

  <Accordion title="Amount is 0">
    *No error message*\
    Points value given is zero. No points added, no logs or errors created.
  </Accordion>

  <Accordion title="Point account not found or exists more than once">
    *No error message*\
    Point account with the specified definition does not exist, or exists several times. Creation of new account is not working as intended. An exception is created.
  </Accordion>

  <Accordion title="ExpireAfterMonthsInactive is negative">
    *Other error message: \[\[error]] In data that was not valid: \[\[notAccepted]]*\
    The value `ExpireAfterMonthsInactive` is negative. File line will be skipped and the error logged.
  </Accordion>

  <Accordion title="ExpireAfterMonthsInactive is zero">
    *Other error message: \[\[error]] In data that was not valid: \[\[notAccepted]]*\
    The value `ExpireAfterMonthsInactive` is 0. File line will be skipped and the error logged.
  </Accordion>

  <Accordion title="ExpireAfterMonthsInactive and ValidTo in the same file line">
    *Other error message: \[\[error]]*\
    The value `ExpireAfterMonthsInactive` has a valid integer value and `ValidTo` also has a date value. File line will be skipped and the error logged.
  </Accordion>
</AccordionGroup>
