Import accounts and locations from a spreadsheet

Overview

Create many accounts and their first locations at once from a CSV file, one account and one location per row, up to about 100,000 rows.

Use this when you're onboarding a customer with dozens or hundreds of locations, or migrating from another platform. It's the fastest way to stand up a large book of business.

You'll need a CSV with the required columns (account name, your client_account_id, plan_id, owner first name and email, location name, your client_location_id, address, country, state, city, postal code). The country must already exist in our system; states and cities are created for you if missing. Max 100 MB.

Returns an import_id immediately; the import runs in the background. Check progress with Check import status. Rows with problems (duplicate email, unknown country, unavailable plan) are skipped and reported, the rest go through. Safe to re-run: rows already imported are skipped, so you can fix a few lines and upload again. No welcome emails are sent.

📘

A 202 means the file was received, not that the import has finished. Poll Check import status until status is completed, completed_with_errors or failed. A file without every required column fails as a whole (status failed, with error_message naming the missing columns).

Prerequisites

Base URL

EnvironmentURL
Productionhttps://production-api.shoutaboutus.com
Developmenthttps://development-api.shoutaboutus.com

Endpoint

POST /api/v1/partner/account/bulk-import

Authentication

Partner token

  • The import runs for your partner: accounts are created under it, and duplicates are checked against your partner's existing accounts and locations.
  • Any other token gets 403.

Rate limit

This endpoint has no rate limit.

Request parameters

None.

Request body

Send the file as multipart/form-data.

FieldTypeRequiredDescription
filefileYesThe CSV file, max 100 MB. The header row must contain every required column below. Excel files (.xlsx) are rejected; save as CSV first.

CSV columns, one account and location per row:

ColumnRequiredDescription
account_nameYesAccount name. Max 100 characters, no < or >.
client_account_idYesYour own id for the account: letters, numbers, - and _, max 100 characters. Must be new for your partner (in the file and in your existing accounts), otherwise the row is skipped as duplicate_client_account_id. It's also what makes a re-run skip rows already imported.
plan_idYesA numeric plan id set up for your partner. Otherwise the row is skipped as plan_unavailable.
owner_first_nameYesThe owner's first name. Max 100 characters.
owner_emailYesThe owner's email. Must not already belong to a user, otherwise the row is skipped as duplicate_email.
location_nameYesLocation name. Max 100 characters, no < or >.
client_location_idYesYour own id for the location (same characters as client_account_id). Must be new for your partner, otherwise the row is skipped as duplicate_client_location_id.
addressYesStreet address. Max 255 characters, no < or >.
countryYesCountry code or name. It must already exist; an unknown country skips the row as unknown_country. Countries are never created.
stateYesState code or name. Created under the country when it doesn't exist.
cityYesCity name. Created under the country and state when it doesn't exist.
postal_codeYesPostal code, 3 to 12 characters.
websiteNoThe account's website. Must be a valid URL.
billing_idNoYour billing reference. Max 100 characters.
owner_last_nameNoThe owner's last name.
owner_phoneNoThe owner's phone: 9 to 15 digits, no spaces or symbols.
storeidNoThe location's label. Defaults to the city name when blank.
business_phoneNoThe location's phone: 9 to 15 digits, no spaces or symbols.
site_urlNoThe location's website. Must be a valid URL.
companyindustry_idNoIndustry id. Blank: Home Services. An id that doesn't exist skips the row as invalid_row. When your partner has an industry set, it's used instead of this value.

A row that breaks any other rule (a missing required value, a value too long, a bad email or URL) is skipped as invalid_row.

Request payload

A CSV file (account_bulk_import_sample.csv):

account_name,client_account_id,plan_id,owner_first_name,owner_email,location_name,client_location_id,address,country,state,city,postal_code
Acme Brand,ACC-001,36,Jane,<owner-email>,Acme Sydney,LOC-001,1 George St,AU,NSW,Sydney,2000

Response body

The payload is inside data.

FieldTypeDescription
import_idintegerThe import's id. Use it with Check import status.
statusstringqueued.
messagestringImport received. Processing has been queued.

Response payload

{
  "data": {
    "import_id": 2,
    "status": "queued",
    "message": "Import received. Processing has been queued."
  }
}

Examples

Success payload

See Response payload. The status code is 202.

Error payload

403 Not a partner

{
  "message": "Only a partner account may run a bulk import.",
  "status": "error",
  "errors": []
}

422 Not a CSV file

{
  "message": "The import file must be a .csv file.",
  "errors": {
    "file": ["The import file must be a .csv file."]
  }
}

422 No file

{
  "message": "Please attach the import CSV file.",
  "errors": {
    "file": ["Please attach the import CSV file."]
  }
}

422 File too large

{
  "message": "The import file may not be larger than 100 MB.",
  "errors": {
    "file": ["The import file may not be larger than 100 MB."]
  }
}
StatusMeaning
202The file is received and the import is queued.
401The token is missing, expired or invalid.
403The token isn't a Partner token.
422The file is missing, isn't a CSV, or is larger than 100 MB.
500Unexpected server error.

Example request

curl --request POST \
  --url "https://production-api.shoutaboutus.com/api/v1/partner/account/bulk-import" \
  --header 'Authorization: Bearer <bearer-token>' \
  --header 'Accept: application/json' \
  --form 'file=@account_bulk_import_sample.csv'

Did this page help you?