# API: Packs: home services

| Method | Path | What it does | Scope |
|---|---|---|---|
| GET | `/v1/packs/home-services/estimates` | Estimates being followed up (by status: open, paused, engaged, won, lost, stopped) | `packs:read` |
| POST | `/v1/packs/home-services/estimates` | Add an estimate to follow up (the cadence starts from its sent date) | `packs:write` |
| GET | `/v1/packs/home-services/estimates/:id` | An estimate and its history (touches, replies read, pauses, wakes, hand-offs) | `packs:read` |
| POST | `/v1/packs/home-services/estimates/:id/action` | Won, lost, stop, reopen, resume, pause until a day, or log the customer's reply (read for a pause) | `packs:write` |
| POST | `/v1/packs/home-services/estimates/run` | Run the follow-up pass now: wake paused estimates, read replies, draft due touches (owners) | `settings:write` |
| GET | `/v1/packs/home-services/fsm/availability` | Live technician availability on the connected board (Housecall Pro, Jobber or ServiceTitan) | `packs:read` |
| GET | `/v1/packs/home-services/fsm/bookings` | Bookings proposed, booked, in conflict or failed | `packs:read` |
| POST | `/v1/packs/home-services/fsm/bookings` | Propose a booking on the board (a person books it next; nothing reaches the board yet) | `packs:write` |
| POST | `/v1/packs/home-services/fsm/bookings/:id/book` | Book a proposal onto the board now (policy first; the window is re-checked live; a retry never books twice). Optionally pick another window. | `packs:write` |
| POST | `/v1/packs/home-services/fsm/bookings/:id/cancelled` | Record that a booked job was cancelled on the board (cancel it there; this frees the slot here) | `packs:write` |
| POST | `/v1/packs/home-services/fsm/bookings/:id/reject` | Turn down a proposed booking (it can be proposed again) | `packs:write` |
| GET | `/v1/packs/home-services/missed-calls` | Missed calls and what happened (texted back, called back, booked, escalated) | `packs:read` |
| POST | `/v1/packs/home-services/missed-calls/:id/action` | Mark a missed call contacted, closed or escalated, or reopen it | `packs:write` |
| POST | `/v1/packs/home-services/missed-calls/run` | Run missed-call recovery now (owners) | `settings:write` |
| POST | `/v1/packs/home-services/oncall/calls` | An after-hours call typed in by whoever answered: triaged; an emergency pages the on-call ladder; gas or CO gets the safety script, never a dispatch | `packs:write` |
| GET | `/v1/packs/home-services/oncall/incidents` | After-hours calls from the call to the job's completion | `packs:read` |
| GET | `/v1/packs/home-services/oncall/incidents/:id` | One after-hours call with every page sent up the ladder | `packs:read` |
| POST | `/v1/packs/home-services/oncall/incidents/:id/action` | Confirm, release, en route, on site, complete, cancel, reopen, re-page or escalate an after-hours call (the shift's people, ops and owners) | `packs:write` |
| POST | `/v1/packs/home-services/oncall/run` | Run the on-call pass now: escalate pages nobody confirmed, triage new after-hours calls (owners) | `settings:write` |
| GET | `/v1/packs/home-services/oncall/shifts` | On-call shifts (current and upcoming) | `packs:read` |
| POST | `/v1/packs/home-services/oncall/shifts` | Add an on-call shift: primary, backup and manager (owners) | `settings:write` |
| DELETE | `/v1/packs/home-services/oncall/shifts/:id` | Remove an on-call shift (owners) | `settings:write` |
| GET | `/v1/packs/home-services/qualifications` | Recent qualifications with their route and disposition | `packs:read` |
| POST | `/v1/packs/home-services/qualify` | Qualify a lead by its vertical's rules (budget, homeownership, insurance details, service area) and route it: a booking proposal on the board, the booking page, a live rep, or a task to collect what's missing | `packs:write` |
| GET | `/v1/packs/home-services/service-areas` | Branches and their service areas (ZIP lists, radius) | `packs:read` |
| POST | `/v1/packs/home-services/serviceability` | Is an address in the service area? (US Census geocoder, cached; then each branch's ZIP list or radius) | `packs:read` |
| POST | `/v1/packs/home-services/triage` | Preview how the triage policy reads a caller's words (nothing is paged) | `packs:read` |
| GET | `/v1/packs/home-services/triage-rules` | The triage policy: keyword → class → action (gas and CO are always a safety redirect) | `packs:read` |
| POST | `/v1/packs/home-services/triage-rules` | Add a triage rule (owners) | `settings:write` |
| DELETE | `/v1/packs/home-services/triage-rules/:id` | Remove a triage rule (owners; a seeded rule is turned off, so a reinstall doesn't bring it back) | `settings:write` |
| PUT | `/v1/packs/home-services/triage-rules/:id` | Change a triage rule (owners) | `settings:write` |

## Examples

### GET /v1/packs/home-services/estimates

Estimates being followed up (by status: open, paused, engaged, won, lost, stopped)

```bash
curl -s "https://api.closefinch.com/v1/packs/home-services/estimates" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/estimates`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/packs/home-services/estimates

Add an estimate to follow up (the cadence starts from its sent date)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/estimates" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/estimates`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/packs/home-services/estimates/$ID

An estimate and its history (touches, replies read, pauses, wakes, hand-offs)

```bash
curl -s "https://api.closefinch.com/v1/packs/home-services/estimates/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/estimates/${id}`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/packs/home-services/estimates/$ID/action

Won, lost, stop, reopen, resume, pause until a day, or log the customer's reply (read for a pause)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/estimates/$ID/action" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/estimates/${id}/action`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/packs/home-services/estimates/run

Run the follow-up pass now: wake paused estimates, read replies, draft due touches (owners)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/estimates/run" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/estimates/run`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/packs/home-services/fsm/availability

Live technician availability on the connected board (Housecall Pro, Jobber or ServiceTitan)

```bash
curl -s "https://api.closefinch.com/v1/packs/home-services/fsm/availability" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/fsm/availability`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/packs/home-services/fsm/bookings

Bookings proposed, booked, in conflict or failed

```bash
curl -s "https://api.closefinch.com/v1/packs/home-services/fsm/bookings" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/fsm/bookings`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/packs/home-services/fsm/bookings

Propose a booking on the board (a person books it next; nothing reaches the board yet)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/fsm/bookings" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/fsm/bookings`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/packs/home-services/fsm/bookings/$ID/book

Book a proposal onto the board now (policy first; the window is re-checked live; a retry never books twice). Optionally pick another window.

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/fsm/bookings/$ID/book" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/fsm/bookings/${id}/book`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/packs/home-services/fsm/bookings/$ID/cancelled

Record that a booked job was cancelled on the board (cancel it there; this frees the slot here)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/fsm/bookings/$ID/cancelled" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/fsm/bookings/${id}/cancelled`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/packs/home-services/fsm/bookings/$ID/reject

Turn down a proposed booking (it can be proposed again)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/fsm/bookings/$ID/reject" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/fsm/bookings/${id}/reject`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/packs/home-services/missed-calls

Missed calls and what happened (texted back, called back, booked, escalated)

```bash
curl -s "https://api.closefinch.com/v1/packs/home-services/missed-calls" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/missed-calls`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/packs/home-services/missed-calls/$ID/action

Mark a missed call contacted, closed or escalated, or reopen it

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/missed-calls/$ID/action" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/missed-calls/${id}/action`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/packs/home-services/missed-calls/run

Run missed-call recovery now (owners)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/missed-calls/run" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/missed-calls/run`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/packs/home-services/oncall/calls

An after-hours call typed in by whoever answered: triaged; an emergency pages the on-call ladder; gas or CO gets the safety script, never a dispatch

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/oncall/calls" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/oncall/calls`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/packs/home-services/oncall/incidents

After-hours calls from the call to the job's completion

```bash
curl -s "https://api.closefinch.com/v1/packs/home-services/oncall/incidents" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/oncall/incidents`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/packs/home-services/oncall/incidents/$ID

One after-hours call with every page sent up the ladder

```bash
curl -s "https://api.closefinch.com/v1/packs/home-services/oncall/incidents/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/oncall/incidents/${id}`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/packs/home-services/oncall/incidents/$ID/action

Confirm, release, en route, on site, complete, cancel, reopen, re-page or escalate an after-hours call (the shift's people, ops and owners)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/oncall/incidents/$ID/action" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/oncall/incidents/${id}/action`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/packs/home-services/oncall/run

Run the on-call pass now: escalate pages nobody confirmed, triage new after-hours calls (owners)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/oncall/run" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/oncall/run`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/packs/home-services/oncall/shifts

On-call shifts (current and upcoming)

```bash
curl -s "https://api.closefinch.com/v1/packs/home-services/oncall/shifts" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/oncall/shifts`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/packs/home-services/oncall/shifts

Add an on-call shift: primary, backup and manager (owners)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/oncall/shifts" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/oncall/shifts`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### DELETE /v1/packs/home-services/oncall/shifts/$ID

Remove an on-call shift (owners)

```bash
curl -s -X DELETE "https://api.closefinch.com/v1/packs/home-services/oncall/shifts/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/oncall/shifts/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/packs/home-services/qualifications

Recent qualifications with their route and disposition

```bash
curl -s "https://api.closefinch.com/v1/packs/home-services/qualifications" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/qualifications`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/packs/home-services/qualify

Qualify a lead by its vertical's rules (budget, homeownership, insurance details, service area) and route it: a booking proposal on the board, the booking page, a live rep, or a task to collect what's missing

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/qualify" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/qualify`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/packs/home-services/service-areas

Branches and their service areas (ZIP lists, radius)

```bash
curl -s "https://api.closefinch.com/v1/packs/home-services/service-areas" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/service-areas`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/packs/home-services/serviceability

Is an address in the service area? (US Census geocoder, cached; then each branch's ZIP list or radius)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/serviceability" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/serviceability`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### POST /v1/packs/home-services/triage

Preview how the triage policy reads a caller's words (nothing is paged)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/triage" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/triage`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### GET /v1/packs/home-services/triage-rules

The triage policy: keyword → class → action (gas and CO are always a safety redirect)

```bash
curl -s "https://api.closefinch.com/v1/packs/home-services/triage-rules" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/triage-rules`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/packs/home-services/triage-rules

Add a triage rule (owners)

```bash
curl -s -X POST "https://api.closefinch.com/v1/packs/home-services/triage-rules" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/triage-rules`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

### DELETE /v1/packs/home-services/triage-rules/$ID

Remove a triage rule (owners; a seeded rule is turned off, so a reinstall doesn't bring it back)

```bash
curl -s -X DELETE "https://api.closefinch.com/v1/packs/home-services/triage-rules/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/triage-rules/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### PUT /v1/packs/home-services/triage-rules/$ID

Change a triage rule (owners)

```bash
curl -s -X PUT "https://api.closefinch.com/v1/packs/home-services/triage-rules/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/packs/home-services/triage-rules/${id}`, {
  method: "PUT",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
  body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();
```

Request and response schemas: [https://www.closefinch.com/openapi.json](https://www.closefinch.com/openapi.json). All resources: [API reference](https://www.closefinch.com/docs/api).
