Creates a technician membership under the current business. If the phone/email matches an existing user, their account is linked. Otherwise a new user identity is created. Either way the membership starts active. The new member is notified (live mode only, best-effort): an email when `email` is supplied, an SMS when `phone` is supplied, both when both — informational only, no activation step (login stays passwordless: magic link / OTP). Re-adding someone: if the person is currently SUSPENDED on this business (a dashboard action — not reachable via this API), the create REACTIVATES that existing membership (same technician id, their existing group; also notified). A technician REMOVED with deleteTechnician is a closed membership: re-adding the same email/phone links the SAME underlying person (no duplicate identity) but creates a FRESH membership with a NEW id — history stays under the old one. Owner/Administrator groups cannot be assigned via API key, and not at all in sandbox mode.
Optional relations (all validated; any missing id → 404 TECHNICIAN_NOT_FOUND with `missing_ids`): `buddy_ids` sets this technician's buddy list (use when creating a lead); `lead_ids` adds this technician as a buddy of each named lead (use when creating a buddy — the buddy-side way to attach the same lead↔buddy relation); `service_area_ids` assigns the technician to those service areas.
`start_location_type=office` snapshots the business address + coordinates into the technician at create time; `address`, `start_location_lat`, `start_location_long` in the body are ignored. Requires the business to have coordinates set (else 400 BUSINESS_LOCATION_MISSING). `start_location_type=home` (or empty) uses the address + coordinates from the body.
Arguments
Idempotency-Keystringheaderoptional
Unique key making retries safe: a repeat send with the same key replays the original response (header Idempotent-Replayed: true) instead of re-running the operation. Reusing a key with a different body returns 422 IDEMPOTENCY_KEY_REUSE.
▾addressobjectbodyoptional
Home address (the day-start point when start_location_type=home).
citystringbodyoptional
City / locality.
countrystringbodyoptional
Country (free-form or ISO code).
formattedstringbodyoptional
Full display string; when set it wins over the discrete parts for display.
linestringbodyoptional
Street line 1.
line2stringbodyoptional
Street line 2 (unit, suite).
postal_codestringbodyoptional
Postal / ZIP code.
statestringbodyoptional
State / province / region.
assignment_tierenumbodyoptional
Crew tier the matching engine assigns by: lead (can head a job), buddy
(crew helper), float (excluded from auto crew-assign).
buddy_idsarray<string>bodyoptional
Buddies of this technician (set when creating a lead). Optional; max 50 technician ids.
business_group_idstringbodyrequired
Role group for the new member. Discover IDs via GET /permission/groups
(Owner/Administrator groups are rejected in sandbox mode).
emailstringbodyoptional
Email address. At least one of phone/email is required (identity resolution key).
full_namestringbodyrequired
The person's full display name. Required; max 255 chars.
job_titlestringbodyoptional
Display title (e.g. "Senior HVAC Technician").
join_datestringbodyoptional
First working day (YYYY-MM-DD).
lead_idsarray<string>bodyoptional
Leads this technician is a buddy of (set when creating a buddy; the
technician is appended to each lead's buddy list). Optional; max 50 technician ids.
notifybooleanbodyoptional
Whether to send the new member the "you have been added to {business}"
message (email when an email was supplied, SMS when a phone was, both
when both). Omitted or true sends it; false stays silent. Set false for
bulk imports so seeding a roster does not text everybody at once.
phonestringbodyoptional
Phone number in E.164 international format: a leading `+` and the country
code, e.g. `+16135550188`. A bare national number (`6135550188`) is
REJECTED with PHONE_INVALID — there is no default region to guess the
country from. At least one of phone/email is required (identity resolution key).
service_area_idsarray<string>bodyoptional
Service areas to assign the technician to. Optional; max 50. Discover via GET /service-areas.
start_location_latnumberbodyoptional
Explicit day-start latitude in decimal degrees (-90..90); when set it wins over the address geocode.
start_location_longnumberbodyoptional
Explicit day-start longitude in decimal degrees (-180..180); when set it wins over the address geocode.
start_location_typeenumbodyoptional
Where the technician starts their day: home (their address) or office
(the business location). Drives the engine's travel estimates.