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

# User import CSV

> Create and update users in bulk with a CSV file.

The user import lets you create and update users in bulk. Users are matched by
**phone number**: an existing user is updated, and a new user is created if no
match is found.

<Note>
  **Delivery:** place the file in the SFTP inbound directory provisioned for
  your account. Sotto picks up new files automatically and routes them by their
  filename prefix — a file must start with `user` to be processed as a user
  import. Files whose name doesn't match a known type are not processed.
</Note>

## File requirements

| Property       | Value                                                |
| -------------- | ---------------------------------------------------- |
| Format         | CSV (comma-separated values)                         |
| Encoding       | UTF-8                                                |
| Filename       | Prefixed with `user_`                                |
| Delimiter      | Comma (`,`)                                          |
| Text qualifier | Optional; required only for values containing commas |
| Header row     | Required. Optional columns may be omitted entirely.  |
| Date format    | `MM/DD/YYYY`                                         |
| Phone format   | E.164 (e.g. `+15551234567`)                          |

## Standard columns

| Column              | Required | Format                                | Description                                                                    |
| ------------------- | -------- | ------------------------------------- | ------------------------------------------------------------------------------ |
| `phone_number`      | **Yes**  | E.164                                 | Unique identifier for the user. Must include the country code and leading `+`. |
| `messaging_consent` | No       | `opted_in`, `opted_out`, or `initial` | SMS marketing consent. Defaults to `initial` for new users.                    |
| `first_name`        | No       | Text                                  | The user's first name.                                                         |
| `last_name`         | No       | Text                                  | The user's last name.                                                          |
| `email_address`     | No       | Email                                 | The user's email address.                                                      |
| `date_of_birth`     | No       | `MM/DD/YYYY`                          | Invalid formats are skipped with a warning.                                    |
| `postal_code`       | No       | 5-digit US ZIP                        | The user's postal code. US only.                                               |
| `third_party_id`    | No       | Text                                  | Your own unique identifier for the user.                                       |

## Custom data columns

Import business-specific attributes by prefixing the column name with
`custom_`, followed by the configured field name: `custom_{field_name}`. For
example, a field named "Loyalty Tier" maps to the column `custom_loyalty_tier`.

<Info>
  Only custom fields already configured for your brand are processed.
  Unrecognized custom columns are skipped with a warning. You can list your
  configured fields with the [Custom Data endpoint](/api-reference/custom-data/list-custom-data-fields).
</Info>

| Data type | Format                              | Example                     |
| --------- | ----------------------------------- | --------------------------- |
| Integer   | Whole number                        | `42`                        |
| Float     | Decimal number                      | `19.99`                     |
| String    | Text                                | `gold`                      |
| Boolean   | `true` / `false` (case-insensitive) | `TRUE`                      |
| List      | Pipe-delimited values               | `electronics\|gaming\|tech` |

## Example

```text theme={"dark"}
phone_number,first_name,last_name,email_address,messaging_consent,date_of_birth,third_party_id,custom_loyalty_tier,custom_interests,custom_vip_status
+12025551234,John,Doe,john@example.com,opted_in,03/15/1990,CUST-001,gold,electronics|gaming|tech,true
+12025551235,Jane,Smith,jane@example.com,initial,07/22/1985,CUST-002,silver,fashion|beauty,false
+12025551236,Bob,Johnson,bob@example.com,,12/01/1992,CUST-003,bronze,,false
```

## Behavior

<Tabs>
  <Tab title="New users">
    * Rows with a valid phone number that doesn't match an existing user create a new record.
    * Missing optional fields are left blank.
    * Custom data is set from the provided values.
  </Tab>

  <Tab title="Existing users">
    * Users are matched by phone number.
    * Only provided fields are updated — empty fields do not overwrite existing data.
    * Custom data values are updated or added as specified.
  </Tab>
</Tabs>

## Error handling

| Condition                         | Behavior                           | Impact                   |
| --------------------------------- | ---------------------------------- | ------------------------ |
| Invalid phone number              | Row skipped, error logged          | User not created/updated |
| Invalid `messaging_consent` value | Row skipped, error logged          | User not created/updated |
| Invalid date format               | Date field skipped, warning logged | Rest of row processed    |
| Custom data type conversion error | Field skipped, warning logged      | Rest of row processed    |
| Unrecognized custom field         | Field skipped, warning logged      | Rest of row processed    |
| Missing `phone_number` column     | Import aborted                     | No users processed       |

## Before you import

<Steps>
  <Step title="Confirm the phone_number column exists">
    It is the only required column, and every value must be valid E.164.
  </Step>

  <Step title="Validate consent values">
    `messaging_consent`, if present, must be `opted_in`, `opted_out`, or `initial`.
  </Step>

  <Step title="Check dates and custom columns">
    Dates use `MM/DD/YYYY`; custom columns use the `custom_` prefix and
    pipe-delimited lists.
  </Step>
</Steps>
