Bulk import accounts + locations (CSV upload)

Bulk-imports accounts from a single CSV — one account + one location (store) per row — designed for up to ~100K rows. The endpoint validates the upload for shape/size, stored, and queued; processing runs asynchronously on the bulk queue (prepare, then parallel chunk jobs, then finalize). Returns an import_id immediately — poll Bulk import status for progress.

Per created row the system provisions the full cascade: account company (bundle_id=3), company_plans, company_options, owner user + person, location-account company (bundle_id=2), store, store_options, store_plans, and store_review_sites (one per the plan's review-site set). The endpoint suppresses welcome/notification emails for bulk imports; The endpoint creates every owner with a temporary password and must set their own at first login.

Auth

  • Partner — authentication. Caller must be a partner company (company bundle_id = 1); The endpoint scopes the import to that partner. Non-partner callers get 403.

Rate limit

  • No rate limit (bulk import — the bulk worker controls back-pressure).

Body (multipart/form-data)

FieldTypeRequiredNotes
filefile (.csv)RequiredCSV only, max 100 MB. Header row must contain every required column below. The endpoint rejects the xlsx (streamed row-by-row for memory safety).

CSV columns — one account+location per row

ColumnRequiredNotes
account_nameRequiredAccount name (max 100, no <>).
client_account_idRequiredPartner-unique external account id (^[A-Za-z0-9_-]+$, max 100). Duplicate (in-file or existing) → skipped duplicate_client_account_id. Also the re-run idempotency key.
plan_idRequiredNumeric plan id assigned to the partner (company_plans). Unassigned → skipped plan_unavailable.
owner_first_nameRequiredAccount owner first name.
owner_emailRequiredGlobally unique on users. Duplicate → skipped duplicate_email.
location_nameRequiredLocation/store name (max 100, no <>).
client_location_idRequiredPartner-unique external location id (same charset). Duplicate → skipped duplicate_client_location_id.
addressRequiredmax 255, no <>.
countryRequiredCountry code or name; must already exist (unknown falls back to skipped unknown_country). Countries are never auto-created.
stateRequiredState code or name; created under the country when missing.
cityRequiredCity name; created under (country, state) when missing.
postal_codeRequired3–12 chars.
websiteOptionalURL — account website.
billing_idOptionalmax 100.
owner_last_nameOptionalAccount owner last name.
owner_phoneOptional9–15 digits, no spaces/symbols.
storeidOptionalStore label; defaults to the resolved city name when blank.
business_phoneOptional9–15 digits.
site_urlOptionalURL — location website.
companyindustry_idOptionalIndustry id; blank, then defaults to Home Services. Non-existent id, then skipped invalid_row. A partner-level industry still overrides the per-row value when set.

Behaviour

  • 202 Accepted{ data: { import_id, status: "queued" } } — the response returns immediately with an import_id. The import itself runs in the background, so poll the status endpoint rather than treating 202 as "import finished".
  • Validation, de-dupe (in-file + against the partner's existing accounts/locations) and geo resolve/create all happen in the single-threaded prepare stage. The endpoint records invalid/duplicate rows and skipped while the rest continue (skip-and-report).
  • Safe to re-run: re-uploading the same file only creates rows whose client_account_id / client_location_id don't already exist for the partner.
  • 403 if the caller is not a partner; 422 if the file is missing, not a .csv, or larger than 100 MB.
Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…
Body Params
file
Responses

Language
Credentials
Bearer
JWT
URL
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
application/json