# Managing contacts

**Contacts** holds every person and company that buys from your store: accounts created through the storefront, guests who checked out without registering, and contacts you add yourself. It appears as **Contacts** in the sidebar for every business — unlike most groups, it does not depend on a module being enabled — with two pages: **Contacts** (the list) and **Groups**.

Contacts are created automatically when someone orders through your storefront. You can also add them by hand or import them in bulk from a CSV file.

## Person and company contacts

Every contact has a **kind**: **Person** or **Company**. A person contact is what you had before — a name, email, phone. A company contact adds business fields: company name, registration number (for example a Dutch KvK number), and VAT id. Set the kind with the Person/Company switch when creating or editing a contact.

Company contacts do not need an email address — some businesses invoice a company without ever emailing an individual there. Person contacts created through your storefront always have one (the storefront's own registration requires it); a company contact added from the dashboard or CSV import can be created without one.

Every contact can also carry an **external id** — a free-text identifier you assign, for example an ERP or accounting system reference, useful for matching contacts across systems during CSV import and export.

## The contact list

Open **Contacts** in the sidebar. The list shows all contacts with these columns:

| Column | Description |
| --- | --- |
| Name | The contact's display name: the company name for a company contact, the person's name otherwise. A neutral **Guest** badge appears next to it when the contact checked out as a guest. Sortable. |
| Email | The contact's email address. Shows `-` when empty. Sortable. |
| Phone | Shows `-` when empty. Hidden on narrow screens. |
| Type | `B2B` or `B2C`. Hidden on narrow screens. |
| Since | The date the contact was created. Hidden on narrow screens. |

Use the search field above the table to find contacts by name, email, company name, or external id; the table paginates with **Previous** / **Next** and a total count. Click any row to open that contact's detail page.

If you have no contacts yet, the list shows "No contacts yet" with **New contact** and **Import CSV** buttons to get started.

### Export all contacts as CSV

Click **Export CSV** at the top of the list. The file `customers.csv` downloads immediately with all your contacts, including the company fields; there is no options dialog.

This is different from the per-contact **Export data** button on the detail page, which produces a GDPR data export for one contact (see [Privacy and GDPR](#privacy-and-gdpr) below).

### Import contacts from CSV

1. Click **Import CSV** at the top of the list.
2. In the **Import contacts** dialog, choose a `.csv` file. The **Import** button stays disabled until a file is selected.
3. Click **Import**. The button shows **Importing...** while the file uploads.

The CSV must follow these rules:

| Requirement | Detail |
| --- | --- |
| Required columns | `name` |
| Optional columns | `email`, `phone`, `internal_notes`, `created_at`, `kind`, `company_name`, `registration_number`, `vat_id`, `external_id` |
| Maximum rows | 1000 |
| Maximum file size | 2 MB |
| Duplicate emails | Rows whose email already exists are skipped and reported as row errors (rows with no email skip this check) |
| Duplicate external ids | Rows whose external id already exists are skipped and reported as row errors |

`email` is optional in the file precisely because a company contact may not have one; when a row omits `kind` it defaults to `person`. After the import runs, the dialog reports how many contacts were imported (for example "Imported 12 contacts.") and, if some rows failed, how many, with a scrollable per-row error list ("Row 3: ..."). The **Cancel** button is relabeled **Close** once a result is shown, and the contact list refreshes automatically after a successful import.

### Delete contacts in bulk

Select contacts with the checkboxes in the list, then run the **Delete** bulk action. A confirmation dialog appears before anything is deleted. Deleting removes the contact records; if you need to erase a contact's personal data for a GDPR request instead, use **Anonymize contact** on the detail page.

## Create a contact

1. Click **New contact** on the contact list.
2. Choose the kind with the **Person** / **Company** switch, then fill in the profile:

   | Field | Shown for | Description |
   | --- | --- | --- |
   | Name | Person and Company | Required. For a company contact, this is the person you deal with (a contact person), not the company itself. |
   | Company name | Company only | Required for a company contact. |
   | Registration number | Company only | Optional, for example a KvK number. |
   | VAT id | Company only | Optional. Spaces are stripped and the value is uppercased before it is validated as 4 to 20 letters and digits — a country prefix is not required, so non-EU formats such as a Turkish VKN are accepted (for example `NL123456789B01` or `1234567890`). |
   | External id | Person and Company | Optional. Your own reference for this contact, for example an ERP id. Must be unique. |
   | Email | Person and Company | Required for a person contact; optional for a company contact. |
   | Phone | Person and Company | Optional. |
   | Internal notes | Person and Company | Optional. Notes only your team can see. |

3. Click **Create contact**. You are taken to the new contact's detail page.

Contacts created this way have no password; the page notes they are "Created without a password; the contact can set one later through the storefront." Validation problems (for example an email that is already in use) appear under the field they concern.

## Contact detail

Click a contact in the list to open their detail page. The header shows the contact's display name (company name when there is one), their email as a clickable mail link when present, and their phone number (when present) as a clickable call link. In the Account card, above the Type and Group selects, a neutral **Guest** badge appears when the contact is a guest, and a B2B status badge is always shown (see [B2B approval](#approve-or-reject-a-b2b-account)).

The page is organized into cards: Account, Profile, Internal notes, Addresses, Orders, and Privacy & data.

### Account type and group

The Account card has two selects:

- **Type**: B2C or B2B.
- **Group**: **No group** or one of your contact groups.

Both save immediately when you change them; there is no save button on this card. If the server rejects the change, the select reverts to the last saved value.

### Approve or reject a B2B account

Every contact shows a B2B status badge:

| Status | Meaning |
| --- | --- |
| Not applicable | The contact is not a B2B account. |
| Pending approval | The contact applied for a B2B account and is waiting for your decision. |
| Approved | You approved the B2B account. |
| Rejected | You rejected the B2B application. |

When a contact's type is B2B and their status is **Pending approval**, the Account card shows two buttons:

- **Approve**: confirms with "Approve this B2B account?" and marks the contact as an approved B2B contact.
- **Reject** (destructive): confirms with "Reject this B2B account?" and marks the contact as a rejected B2B applicant.

These buttons only exist while the status is pending. Once you approve or reject, there is no button to reverse the decision, so decide carefully.

### Edit the profile

The Profile card lets you edit the same fields as on creation: **Name**, the **Person** / **Company** switch and its company fields (**Company name**, **Registration number**, **VAT id**), **External id**, **Email**, and **Phone**. Name is always required; Company name is required only when the kind is Company. Email is optional for every contact you create here — only a contact registering through the storefront must have one. Unlike the Account card, these fields are not saved automatically: click **Save changes**. The button shows **Saving...** while the update runs and a "Saved." confirmation for a moment afterwards. Validation errors appear under the field they concern.

### Internal notes

The Internal notes card holds free-form text with the placeholder "Notes visible to your team only". Click **Save notes** to store them. These notes are never shown to the contact, but they are included in the contact's GDPR data export, so keep them professional.

### Addresses

The Addresses card lists the contact's saved addresses, read-only: each shows a badge with the address type (`shipping`, `billing`, or `work`), a **default** badge on the default address, an optional label, and the name, street, postal code, city, and country. Contacts manage their own addresses through the storefront; you cannot edit them here. When there are none, the card shows "No saved addresses."

The **work** address type covers a business site distinct from where invoices go (`billing`) or goods ship to (`shipping`) — for example a company contact's office or project location.

### Order history

The Orders card lists the contact's most recent orders, up to 50, with columns:

| Column | Description |
| --- | --- |
| Number | The order number, shown as `#1024`. Links to the order. |
| Status | The order's status. Shown here as the raw status value (for example `pending`), not the colored badge used in the orders module. |
| Placed | The order date. Hidden on narrow screens. |
| Total | The order total. |

Click a row to open the order in the Commerce module. If the Commerce module is not enabled for your store, the card shows "Commerce is not enabled." instead; with no orders it shows "No orders yet."

## Privacy and GDPR

The Privacy & data card on the contact detail page covers data-protection requests.

### Export a contact's data

Click **Export data** to download everything stored about the contact, including the company fields, as a JSON file (`customer-{id}.json`). The button shows **Exporting...** while the file is prepared. Use this to answer a data-access request.

### Anonymize a contact

Click the destructive **Anonymize contact** button to fulfill a right-to-erasure request. The confirmation dialog "Anonymize this contact?" warns you what happens:

- Name, email, phone, internal notes, company name, registration number, VAT id, and external id are scrubbed.
- Saved addresses are permanently deleted.
- Active storefront logins are revoked.
- The record is removed from your contact list.

This cannot be undone. Confirm with **Anonymize permanently**; you are then returned to the contact list.

## Contact groups

Groups let you apply shared pricing, discounts, and checkout rules to a set of contacts, person or company alike. Open **Groups** in the Contacts sidebar. The list shows each group's **Name** (sortable), **Slug**, and **Status** badge (**Active** / **Inactive**), with a search field above it. There is no group detail page: everything happens in a dialog on this page.

To assign a contact to a group, use the **Group** select on that contact's detail page.

### Create or edit a group

1. Click **New group** (or **Edit** on an existing row).
2. Fill in the dialog:

   | Field | Description |
   | --- | --- |
   | Name | Required; the save button stays disabled while it is blank. |
   | Slug | Auto-generated from the name until you edit it manually. Leave it blank to let the server derive one. |
   | Description | Optional. |
   | Price adjustment | A percentage from `-100` to `999.99`. Negative = discount, positive = surcharge. Applied to all catalog prices for members. |
   | Cart identity mode override | **Inherit from cart settings**, **Guest checkout allowed**, **Login required**, or **Guest only**. Overrides your store-wide cart identity setting for members of this group. |
   | Always require a quote | Only shown when the Sales module is enabled, because the quote flow belongs to Sales. When on, members of this group always go through the quote flow, regardless of cart thresholds. It only takes effect while quote requests are switched on under [Sales → Settings → Quotes](/docs/sales/settings#quote-requests). |

3. Click **Save changes**.

The **Status** column shows whether a group is Active or Inactive, but there is no control on this page to change it.

### Delete a group

Click the destructive **Delete** button on the group's row and confirm in the "Delete this group?" dialog. A group that still has members cannot be deleted: the dashboard shows an error like "Contact group has 2 member(s). Reassign them first." Move those contacts to another group (or **No group**) on their detail pages first.
