HeavySet Tech Server‑to‑Server (S2S) API Suite
HeavySet’s S2S endpoints are purpose‑built for machine‑to‑machine communication. Unlike our page‑level (iframe) or public JavaScript SDK APIs, these routes live entirely on the backend, letting your services fetch or push data without exposing credentials, running browser‑side code, or worrying about cross‑origin restrictions.
Supported CRMs: Improveit360 Classic/Enterprise, HeavySet Basic, BuilderPrime
Authentication at a glance
- Create an Access Token in Admin → Appointment Page → Access Tokens (leave Origin Domain blank).
- Include the token as the
tokenfield in every request body. - No bearer headers, cookies, or JWT exchanges are required.
Endpoint Catalogue
Base URL: https://api.heavyset.tech/api/v1/appointment/s2s
| Route | Method | Purpose |
|---|---|---|
/phone/query | GET | Look up an existing lead by phone #. |
/phone/query/blocks | GET | Available appointment blocks for that lead. |
/phone/query/dispositions | GET | Retrieve list of Not Qualified disposition reasons. |
/phone/update | PATCH | Partially update a lead and optionally cancel or (re)schedule an appointment. |
/phone/query/{crmSettingsId} | GET | Low-latency lead lookup (Oregon or Virginia region). Contact HeavySet Tech to enable. |
The sections below document each route in detail.
🛈 Common Request Pieces
| Part | Where | Example |
| Access Token | Headerx-hs-token | (token is a very long encrypted string) |
| Phone Number | Query stringphone | +18015551234 |
Phone Query
Lookup an existing lead—and any associated appointment data—by phone number. The lookup is executed against the lead record in your connected CRM (e.g., Salesforce, HubSpot). HeavySet acts as a passthrough proxy, ensuring you always receive the freshest data available.
Endpoint
| Method | GET |
| URL | https://api.heavyset.tech/api/v1/appointment/s2s/phone/query |
Part of the S2S (server‑to‑server) family of endpoints. No browser origin or CORS checks are applied.
Request
GET /api/v1/appointment/s2s/phone/query?phone=%2B18015551234 HTTP/1.1
x-hs-token: hs_live_03fogRY2p8V34scURL
curl -G "https://api.heavyset.tech/api/v1/appointment/s2s/phone/query" \
-H "x-hs-token: hs_live_03fogRY2p8V34s" \
--data-urlencode "phone=+18015551234"
Response
HTTP 200 OK returns an ExistingLead object populated directly from your connected CRM when a match is found.
Example
{
"name": "Jane Doe",
"address1": "123 Main St",
"address2": null,
"city": "Denver",
"state": "Colorado",
"stateAlpha2": "CO",
"zip": "80202",
"country": "United States",
"countryAlpha2": "US",
"countryAlpha3": "USA",
"phone": "+18015551234",
"leadId": "a0B8X00000DXabc",
"prospectId": "p0P8X00000PXabc",
"createdDate": "2025-03-14T20:25:31.000Z",
"appointmentStatus": "Confirmed",
"appointmentStart": "2025-05-16T15:00:00.000Z",
"appointmentEnd": "2025-05-16T16:00:00.000Z",
"appointmentStartAMPM": "3:00 pm",
"appointmentEndAMPM": "4:00 pm",
"source": "landing-page",
"sourceType": "web",
"optOutText": false,
"optOutEmail": false,
"tcpa": true,
"email": "jane@example.com",
"marketSegment": "Residential",
"blockId": "a0p8X00000XRDoJQAX",
"optIn": true,
"product": "Solar",
"disposition": "Appointment Set",
"hearAbout": "Google Search",
"homeYear": "1998",
"salesRepName": "John Smith",
"salesRepEmail": "john@heavyset.tech",
"salesRepAvatarUrl": "https://cdn.heavyset.tech/avatars/john.png"
}
Property reference (ExistingLead)
| Field | Type | Description |
|---|---|---|
name | string | Lead’s full name. |
address1 | string | Primary street address. |
address2 | string? | Suite, Apt, Unit, etc. |
city | string | City. |
state | string | State/Province (full). |
stateAlpha2 | string | Two‑letter code. |
zip | string | Postal code. |
country | string | Country (full). |
countryAlpha2 | string | ISO‑3166‑1 alpha‑2. |
countryAlpha3 | string | ISO‑3166‑1 alpha‑3. |
phone | string | Canonical phone number. |
leadId | string? | HeavySet internal lead ID. |
prospectId | string? | Legacy prospect ID. |
createdDate | Date? | When the lead was first created (UTC). |
appointmentStatus | string? | Confirmed, Cancelled, etc. |
appointmentStart | Date? | Appointment start (UTC). |
appointmentEnd | Date? | Appointment end (UTC). |
appointmentStartAMPM | string? | Readable local start. |
appointmentEndAMPM | string? | Readable local end. |
source | string? | Marketing source tag. |
sourceType | string? | Channel type (e.g. web). |
optOutText | boolean? | SMS opt‑out flag. |
optOutEmail | boolean? | Email opt‑out flag. |
tcpa | boolean? | TCPA consent flag. |
email | string? | Lead email. |
marketSegment | string? | Tampa, Jackson, etc. |
blockId | string? | Appointment block ID. |
optIn | boolean? | Checked opt in checkbox on form |
product | string? | Interested product |
disposition | string? | Unlikely to have this |
hearAbout | string? | Unlikely to have this |
homeYear | string? | Unlikely to have this |
salesRepName | string? | Unlikely to have this unless appointment |
salesRepEmail | string? | Unlikely to have this |
salesRepAvatarUrl | string? | Unlikely to have this |
Low‑Latency Phone Query
When to use: You need sub‑100 ms lookups for callers in or near Oregon (U.S. West) or Virginia (U.S. East). The endpoint is fronted by an edge cluster physically located in Oregon or Virginia. Functionality is identical to
/phone/query, but requires acrmSettingsIdpath parameter so the service can route requests without an extra origin lookup.
| Method | GET |
| URL | https://api-oregon-s2s.heavyset.tech/api/v1/appointment/s2s/phone/query/{crmSettingsId} |
| URL | https://api-virginia-s2s.heavyset.tech/api/v1/appointment/s2s/phone/query/{crmSettingsId} |
Path parameter
| Name | Type | Description |
crmSettingsId | string | Identifier for the CRM configuration supplied by HeavySet. |
Request
curl -G "https://api-oregon-s2s.heavyset.tech/api/v1/appointment/s2s/phone/query/a0B8X00000DXabc" \
-H "x-hs-token: hs_live_03fogRY2p8V34s" \
--data-urlencode "phone=+18015555555"All headers and query parameters mirror those of the standard /phone/query endpoint. Response payload is the same ExistingLead object.
Phone Query + Blocks
Calculates availabilities for that lead’s ZIP/product, returning a TimeSlotsDto.
Endpoint
| Method | GET |
| URL | https://api.heavyset.tech/api/v1/appointment/s2s/phone/query/blocks |
Query Params
phone | string | Requested |
simpleBlockId | boolean? | If true, blockIds will be returns as simple values starting at 20 |
limitDays | number? | limit slots to fix X business days from today |
Request
GET /api/v1/appointment/s2s/phone/query/blocks?phone=%2B18015551234 HTTP/1.1
x-hs-token: hs_live_03fogRY2p8V34sGETcURL
curl -G "https://api.heavyset.tech/api/v1/appointment/s2s/phone/query/blocks" \
-H "x-hs-token: hs_live_03fogRY2p8V34s" \
--data-urlencode "phone=+18015551234"
Response
HTTP 200 OK returns an TimeSlotsDto object populated directly from your connected CRM when a match is found.
Example
{
"timeZone": "America/New_York",
"slots": [
{
"appointmentDate": "2025-05-20",
"startTime": "10:00 AM",
"endTime": "11:30 AM",
"availableSlots": 3,
"blockId": "a0p8X00000XRDoJQAX",
"timeZone": "America/New_York"
},
{
"appointmentDate": "2025-05-20",
"startTime": "2:00 PM",
"endTime": "3:30 PM",
"availableSlots": 1,
"blockId": "a0p8X00000XRDoJQ2B",
"timeZone": "America/New_York"
}
]
}
Property reference (TimeSlotsDto)
| Field | Type | Description |
|---|---|---|
timeZone | string? | IANA zone for the slot list (e.g. America/New_York). |
slots | TimeSlotDto[] | Array of slot objects below |
Property reference (TimeSlotDto)
| Field | Type | Example | Description |
|---|---|---|---|
appointmentDate | string | 2025-05-20 | Calendar date (YYYY‑MM‑DD). |
startTime | string | 10:00 AM | Local start time. |
endTime | string | 11:30 AM | Local start time. |
availableSlots | number | 3 | Remaining schedulable spots in that block. |
blockId | string | a0p8X00000XRDoJQAX | Block identifier for subsequent booking. |
timeZone | string | America/New_York | Fallback IANA zone corresponding to the times. |
Phone Dispositions
| Method | GET |
| URL | https://api.heavyset.tech/api/v1/appointment/s2s/phone/query/dispositions |
Returns the list of “Not Qualified” disposition labels configured in your connected CRM. The response is cached per organization for fast repeat access.
Request
GET /api/v1/appointment/s2s/phone/query/dispositions HTTP/1.1
x-hs-token: <access-token>No query parameters or body are required.
Response (HTTP 200 OK)
{
"notQualifiedReasons": [
"Credit too low",
"Roof in poor condition",
"Not homeowner"
]
}| Field | Type | Description |
notQualifiedReasons | string[] | Disposition labels exactly as stored in your CRM. |
Phone Update
Use this route to patch lead details in your connected CRM and optionally cancel or move an appointment—all in a single call. The phone number is the immutable key; it cannot be changed through this endpoint.
Endpoint
| Method | PATCH |
| URL | https://api.heavyset.tech/api/v1/appointment/s2s/phone/update |
Request
Content-Type: application/json
x-hs-token: <access-token>
Idempotency-Key: <uuid> ; optional but recommendedBody schema (PhoneUpdateDto)
| Field | Type | Required | Notes |
phone | string | ✔︎ | Lookup key (E.164 or 10‑digit NANP). Not updatable. |
firstName | string | — | Updates first name. |
lastName | string | — | Updates last name. |
streetAddress | string | — | Street line. |
city | string | — | City (auto‑filled from ZIP if omitted). |
zip | string | — | Triggers auto‑fill of city, state, stateAlpha2, and timeZone. |
email | string | — | Updates email. |
optOutPhone | boolean | — | Do‑not‑call flag. |
tcpaFlag | boolean | — | TCPA consent flag. |
appendComment | string | — | Adds note to lead & appointment. |
cancelAppt | boolean | — | If true, cancels any booked appointment. Mutually exclusive with blockId. |
blockId | string | — | Books or reschedules to this block. Mutually exclusive with cancelAppt. |
simpleBlockId | boolean? | — | If true, the blockId will be checked for a a stored alias. Expected blockId to be a simple value such as 120. |
notQualifiedReason | string | — | Update prospect as not qualified with a saved reason |
homeYear | number? | — | Year home built (optional) |
takerId | string? | — | Update setter & taker on appointment (optional) |
Validation rules
cancelApptandblockIdcannot both be supplied.- Phone‑number fields (
primaryPhone,textPhone) are forbidden and will return400 Bad Requestif present.
Example – update info only
curl -X PATCH "https://api.heavyset.tech/api/v1/appointment/s2s/phone/update" \
-H "Content-Type: application/json" \
-H "x-hs-token: hs_live_03fogRY2p8V34s" \
-H "Idempotency-Key: 7d8c5ea2-1e4d-43f0-a7f1-5fd2f093b766" \
-d '{
"phone": "+18015551234",
"firstName": "Janet",
"email": "janet.d@example.com",
"optOutPhone": false,
"appendComment": "Updated contact info."
}'Example – cancel appointment
{
"phone": "+18015551234",
"cancelAppt": true,
"appendComment": "Customer called to cancel."
}Example – reschedule
{
"phone": "+18015551234",
"blockId": "a0p8X00000XRDoJQAX"
}Response (HTTP 200 OK)
Returns the refreshed ExistingLead object after updates are applied (see reference table above).
Errors
| HTTP | Meaning | Typical Cause |
|---|---|---|
400 Bad Request | Validation failed | Missing/invalid fields. |
401 Unauthorized | Invalid token | Token empty, expired, or revoked. |
404 Not Found | No lead match | Phone not in database. |
429 Too Many Requests | Rate limit exceeded | >60 requests/min. |
500 Internal Server Error | General failure | Unexpected server issue. |
Error payload
{
"statusCode": 400,
"message": [
"phone must be a string",
"token should not be empty"
],
"error": "Bad Request"
}
Use‑case Highlights
- Duplicate prevention – check if a caller already exists before creating a new lead.
- CRM enrichment – pull HeavySet appointment details into your own backend.
- Agent assist – real‑time caller info in custom dialer or IVR flows.
Comments
0 comments
Please sign in to leave a comment.