Skip to main content
POST
Bulk-import contacts from CSV

Authorizations

Authorization
string
header
default:Bearer brew_your_api_key
required

Send your Brew API key as Authorization: Bearer brew_xxx.

Headers

X-Brand-Id
string

The brand this request acts on. REQUIRED for organization-scoped credentials (otherwise 400 BRAND_ID_REQUIRED — there is no default brand); list ids with GET /v1/brands. Brand-scoped credentials may omit it, and sending a different brand returns 403 BRAND_SCOPE_MISMATCH. A brand outside your organization returns 404 BRAND_NOT_FOUND.

Required string length: 1 - 64

Body

application/json
csv
string
required
Required string length: 1 - 5000000
mapping
object
validate
boolean

Optional deliverability check on ingestion. When true, each imported address is validated with the provider and the verdict is saved to the contact’s validationStatus. Imports of at most 100 submitted CSV data rows validate inline, metered at 2 credits per submitted row on a successful response, including skipped rows and repeated addresses. Larger imports write first and use a background validation workflow billed per address as it runs; validationJobId is returned when a job is queued. The job skips unsubscribed, suppressed and recently validated addresses, and a VALIDATION_SKIPPED warning gives the counts; when every address is skipped no job is queued and validationJobId is absent.

Consent record stamped on every imported row (typically { "source": "import" }).

dateOrder
enum<string>

Order for a date column whose dates read either way (03/04/2026): day_first is 3 April, month_first 4 March. A day over 12 in the column overrides it. Default month-first, with a DATE_ORDER_ASSUMED warning.

Available options:
month_first,
day_first
fileName
string

Name this batch is listed under in Import History (usually the source file name, e.g. customers.csv), also stamped on every contact it writes as csvFileName. A path keeps only its last segment.

Required string length: 1 - 255
dryRun
boolean

When true, returns what this import would return and writes nothing: no contacts, fields, Import History entry or importId; validate is skipped and nothing is charged.

onConflict
enum<string>

upsert (default) updates existing contacts; skip only creates missing ones, leaving each existing contact unchanged (counted in summary.skipped, with a CONTACT_EXISTS_SKIPPED warning).

Available options:
upsert,
skip

Response

Import summary (all rows valid).

summary
object
required
fieldsCreated
string[]
required
errors
object[]
required
warnings
object[]
required
validation
object
validationJobId
string
importId
string

This batch's Import History id. Each contact it wrote carries it as importId until a later import touches that contact, so a contact filter on importId lists them. Absent on a dry run.

dryRun
enum<boolean>

Present on a dry run: the counts say what the import would do, and nothing was written.

Available options:
true