---
title: "Import a vCard file into a mailbox's personal contacts"
method: POST
path: "/customers/{id}/domains/{domain}/mailboxes/{address}/contacts/import"
tags: ["Partners"]
---

# Import a vCard file into a mailbox's personal contacts

`POST /customers/{id}/domains/{domain}/mailboxes/{address}/contacts/import`

## Request

- Base URL: `https://faivelo.com/api/partner`
- URL: `https://faivelo.com/api/partner/customers/{id}/domains/{domain}/mailboxes/{address}/contacts/import`
- Auth: HTTP bearer

The address book a person exported from their previous webmail (Roundcube, cPanel, Outlook, Apple, Google: vCard 2.1, 3.0 or 4.0), into this mailbox's PERSONAL address book, never the customer's shared directory. Add-only: a card whose address (any of them) is already in the book is skipped as `exists`; nothing is changed or removed. A card's `CATEGORIES` (comma-separated) become the contact's personal groups: groups that do not exist yet are created, up to 200 per mailbox; a skipped card changes no group. Send the file as the body (`text/vcard`, `text/x-vcard` or `text/plain`) or as JSON `{ "vcf": "..." }`; `?dryRun=1` answers the same report without writing. At most 2 MB of text (**413**) and 5000 cards per call (`truncated: true` past that), 10 000 personal contacts per mailbox (**422** `PERSONAL_CONTACTS_CAP`, before anything is written), 120 calls per 10 minutes per partner. Available together with migrations (**403** `MIGRATION_NOT_AVAILABLE` until then); an inactive mailbox answers **409**. Requires `partner:write`.

## Path parameters

- `id` string, required
- `domain` string, required
- `address` string, required

## Query parameters

- `dryRun` '1' | 'true'

## Request body

- PartnerContactsImportRequest
  - `vcf` string, required: The vCard file text (one or many BEGIN:VCARD blocks), at most 2 MB

## Response `200`

What was imported and what was skipped

- object
  - `success` boolean
  - `data` PartnerContactsImportResult
    - `dryRun` boolean
    - `total` integer: Cards in the file, usable or not
    - `imported` integer: Rows created (0 on a dry run)
    - `planned` integer: Rows the file would create; equals `imported` on a real run unless a concurrent write took an address first
    - `skipped` object
      - `exists` integer: An address of the card is already in the personal book (nothing is changed)
      - `duplicate_in_file` integer: An earlier card in the same file used one of its addresses
      - `no_email` integer: No usable email address on the card
      - `invalid` integer
    - `errors` object[]: The first 50 skipped cards, by position in the file (from 0)
      - `index` integer
      - `reason` 'exists' | 'duplicate_in_file' | 'no_email' | 'invalid'
    - `truncated` boolean: The file held more than 5000 cards; the rest were not read
    - `groupsCreated` integer: Personal contact groups created from the cards' CATEGORIES (on a dry run: how many would be)
    - `memberships` integer: Group memberships written for the imported rows (on a dry run: how many would be)

## Other responses

- `400`: No vCard in the body
- `401`: Missing or invalid API key, or not a partner key
- `403`: The key lacks `partner:write`, or contact import is not available yet (`code: MIGRATION_NOT_AVAILABLE`)
- `404`: Not found, including any customer that is not yours
- `409`: The mailbox is inactive
- `413`: The file is larger than 2 MB
- `422`: The mailbox would pass 10 000 personal contacts (`code: PERSONAL_CONTACTS_CAP`)
- `429`: More than 120 imports in 10 minutes, or the key's per-minute limit

---

[API](https://skmtc.dev/faivelo/apis/faivelo-api.md) · [All operations](https://skmtc.dev/faivelo/apis/faivelo-api/llms.txt) · [OpenAPI document](https://skmtc.dev/faivelo/apis/faivelo-api/revisions/a7413ddea5d1?raw)
