Use this flow when your integration already has a contact file. Preparation never creates or changes a contact. You decide which validated rows to apply and whether they match existing people.
Upload the source
Follow Upload and use files. Use a UTF-8 CSV, TSV, plain-text table or vCard and save the completed file_id. The contact parser supports up to 4,000,000 text characters per file. A larger source is refused; no rows are silently truncated.
Give the key access to customers.PreviewContactImport, customers.CreatePerson, and read/write access to core:Person. Add customers.ListPeople and customers.UpdatePerson if you need to match and update existing contacts. A contact is a customer record; creating one does not invite a workspace member or assign an account role.
Map and review
For a table, map column numbers starting at zero. For example, this source has a header and three columns:
Name,Email,Job title
Alex Morgan,alex@example.com,Operations manager
Taylor Chen,taylor@example.com,Project leadcurl 'https://api.brigg.app/v1/operations/customers.PreviewContactImport' \
-H "Authorization: Bearer $BRIGG_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"file_id":"f_contacts","has_header":true,"mapping":{"display_name":0,"email":1,"title":2},"limit":50}'A vCard describes its own fields, so omit mapping for that format. The supported fields are display_name, email, phone, title and linkedin_url.
{
"file_id": "f_contacts",
"row_count": 2,
"duplicate_count": 0,
"invalid_count": 0,
"items": [
{"row":1,"status":"ready","data":{"display_name":"Alex Morgan","email":"alex@example.com","title":"Operations manager"}},
{"row":2,"status":"ready","data":{"display_name":"Taylor Chen","email":"taylor@example.com","title":"Project lead"}}
],
"has_more": false,
"next_cursor": null
}ready rows contain data that satisfies the published Create person contract. An invalid row contains an explanation. duplicate means an earlier row in this source has the same normalized email, or the same name when there is no email. It does not mean the person already exists in Brigg. Empty source lines are ignored by the parser; row counts parsed contact rows after the header.
When has_more is true, pass next_cursor as cursor with the same file and mapping. Each page checks current file access. A cursor cannot be reused with a different source, mapping or credential.
Apply the reviewed rows
For a new person, send the row's data to Create person:
curl 'https://api.brigg.app/v1/operations/customers.CreatePerson' \
-H "Authorization: Bearer $BRIGG_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: contacts-november-row-1' \
--data '{"data":{"display_name":"Alex Morgan","email":"alex@example.com","title":"Operations manager"}}'Store the returned item.id. Reuse this row's idempotency key when retrying its creation, so a timeout cannot create a duplicate.
If you are reconciling existing contacts, use List people to find candidates and choose the target explicitly before Update person. Preparation does not guess merges or grant permission to write. Skip invalid or duplicate rows until your integration has resolved them. A failed write does not undo other rows: retain each row's result so you can resume safely.