TheHVACMarketing Guys

Open Service Profile for HVAC, plumbing, and electrical contractors

One file on your website tells an AI assistant which ZIP codes you cover, which windows you take requests for, and how you confirm. The phone call still works. The file answers first.

The question comes before the customer does

In 2025, AI assistants began calling local businesses on behalf of customers to ask about prices and availability. In 2026 those calls reached home repair and the other service trades. The assistant asks what your dispatcher hears every day. Do you cover 32174? Can a technician come tomorrow morning? What is the after-hours rate? When the answer is slow, your company is dropped from the shortlist before the customer ever sees it.

None of those answers is a secret. They sit in pieces across your website, your Google Business Profile, and your scheduling software. Today an assistant either calls you to ask, or reads your pages and guesses. Neither is a reliable way onto a shortlist.

What the file says

Open Service Profile is a small file at /.well-known/open-service-profile on your website. It describes your business in a form an AI assistant can read. It says who you are, where you work, what you offer, which ZIP codes or radius you cover, when you are open, and how an assistant may send you a booking request. The standard also defines six tools an assistant can call: five that read facts, and one that sends a booking request.

Every booking is a request. Your site may say a request was received. It may never say an appointment is booked, a time is reserved, or a technician is assigned. You confirm through your own process, by the contact method the customer allowed. The standard is a draft. Our parent company, The Service Marketing Guys, maintains it. It runs on live client sites first.

What this means for a contractor

A contractor tells the file that work happens at the customer's address. The standard calls this the on_site model. That one line decides what else the file must carry and how the tools answer.

ZIP coverage. Coverage is required when you work at the customer's address. It is a list of five-digit ZIP codes, a radius in miles around a location, or both. When an assistant checks a ZIP, your list is checked first, then a location's own ZIP, then the radius. A radius match is only a guide, so the assistant is told to confirm with you. "Not covered" and "not checked" are two different answers, and an assistant must keep them apart. Coverage tells an assistant where you usually work. It is not a gate: the booking tool will not turn down a request just because the ZIP falls outside your listed area. You make that call when you review the request.

Time windows. A window is a block of the day you take requests for. The standard names three, Morning, Afternoon, and Evening. You can publish clock times for each, or add your own windows with a label. A window is open for requests on a day when your hours and rules allow it. That says nothing about how many jobs you can fit. An assistant must call it a window you take requests for, never "available", and its start and end are never a promised arrival time.

The earliest day you accept. You set the earliest day you accept, counted in whole days in your time zone. A 1 means tomorrow at the earliest. A request for an earlier date is refused with an error that names your minimum. When an assistant checks your windows, dates outside your range show as closed, not as errors, so it can show the customer what is open.

After-hours. The file must say whether you take urgent calls outside your published hours. The rate or response time is optional, in your own words. If you leave it out, an assistant must not state any after-hours rate or response time.

The service address. Because work happens at the customer's address, a booking request needs that address by default. Vehicle details are not part of the request. If an assistant sends them anyway, your site ignores them without an error.

A request, not a confirmation. The file says every booking is a request. Version 0.1 defines no other kind. The reply to a request says the appointment is not confirmed and is waiting on you, so no assistant can read silence as a yes. You confirm, in your own words, by the contact method the customer allowed.

Three levels

Each level builds on the one before it. To claim Level 2, a business has to meet everything in Level 1 as well. Your file can say which level you claim, and an assistant checks the claim instead of trusting it. Level 1 exists so a business with only a website and structured data can meet the standard today.

LevelNameWhat the business publishes
1Read-only profileThe file, plus a short block of structured data on your pages. That block points one action at your schedule page, and the result is a pending reservation, not a booked one. No price, certification, hour, or service may be invented. Each one already appears on your own pages or comes from a source you control.
2Read toolsEverything in Level 1, plus three tools an assistant can ask directly: who you are, what you offer, and whether you cover a ZIP code (get_business_info, list_services, check_coverage). Anyone can call them, calls are rate-limited, and the answers must match the file. A reviews tool (get_reviews) is recommended.
3BookingEverything in Level 2, plus a tool that takes a booking request (request_service_booking) and one that says which windows you take requests for (check_availability). The second must at least work from your published hours and booking rules. Every reply, page, email, or text a request triggers says received, never booked.

What you publish to start

Level 1 asks for four things. None needs a server beyond the one already hosting your site.

  1. One file at /.well-known/open-service-profile. It is served as JSON, readable from other sites, and matches the standard's published format. It carries your display name, your trades, where work happens, your phone, your website, and your time zone. It lists each location with its address and hours. It lists each service with the address of its own page. It lists your coverage when work happens at the customer's address. And it holds your booking rules: the windows you offer, how many days ahead a request must be, whether you take weekend dates, whether you take urgent calls after hours, and how you confirm.
  2. A short block of structured data on your pages, the kind Google already reads. It can use the trade type where one exists (HVACBusiness, Plumber, or Electrician). It carries your name, address, phone, hours, and website, matching the file. It points one action at your schedule page, and says the result is a pending reservation, not a booked one. Listing each service in that block with its own action is recommended, not required.
  3. The file says every booking is a request. It also says where work happens and which trades you do.
  4. The file contains no invented facts: every price, certification, hour, and service already appears on your own pages or comes from a source you control. The file carries no ratings or review counts. A business that is not ready publishes nothing rather than a placeholder.

A worked example

The standard ships example files. Palmetto Air & Heat is its two-location HVAC company. The company, its addresses, and its phone numbers are fictional.

Palmetto Air & Heat, two locations, Level 3

Trimmed from Appendix C.1 of the standard.

{
  "specVersion": "0.1",
  "business": { "displayName": "Palmetto Air & Heat", "trades": ["HVACBusiness"], "serviceModel": "on_site", "timeZone": "America/New_York" },
  "locations": [
    { "id": "daytona", "name": "Daytona Beach", "isPrimary": true, "hours": { "weekly": { "monday": { "open": "07:30", "close": "18:00" } } } },
    { "id": "palm-coast", "name": "Palm Coast", "isPrimary": false }
  ],
  "services": [
    { "slug": "ac-repair", "name": "AC repair", "pricePresentation": "Diagnostic $89, applied to the repair" },
    { "slug": "duct-cleaning", "name": "Duct cleaning", "locationIds": ["daytona"] }
  ],
  "coverage": { "postalCodes": ["32114", "32117", "32174", "32176"], "radius": [{ "locationId": "daytona", "miles": 25 }] },
  "bookingPolicy": {
    "windows": [{ "id": "Morning", "start": "08:00", "end": "12:00" }, { "id": "Afternoon", "start": "12:00", "end": "17:00" }],
    "minimumDaysAhead": 1, "weekendRequests": "saturday_only", "emergencyAvailable": true,
    "confirmationNote": "Our office calls or texts within one business hour to confirm the arrival window."
  },
  "bookingSemantics": "request"
}

The full file also lists 13 ZIP codes, five services, full hours for both locations, two holiday closures, three certifications, an after-hours note, and where its tools and schedule page live.

How one request plays out

A customer in Ormond Beach asks an AI assistant for AC repair tomorrow morning, a weekday. The assistant reads the file on Palmetto's site and checks the ZIP, 32174. That ZIP is on Palmetto's published list. The answer is covered, matched by the ZIP list.

Palmetto has two locations, so the assistant picks one, Daytona Beach. It asks which windows Palmetto takes requests for tomorrow (the standard calls this tool check_availability). The answer comes from Palmetto's published hours and booking rules, not a live calendar, and the answer says so. The Morning window is open for requests. The assistant tells the customer that Palmetto accepts requests for tomorrow morning. It does not say the window is available.

The customer sees the service, the date, the window, and the contact details to be sent. The customer approves. Only then does the assistant send the booking request. The reply says the request was received. It says the appointment is not confirmed and is waiting on Palmetto. It passes along Palmetto's own note: the office calls or texts within one business hour to confirm the arrival window. That is what the customer hears.

What it does not do

The standard makes no claim about search visibility or ranking. It defines no payment, deposit, or card capture. It does not require a connected calendar. In version 0.1, the windows you take requests for come from your published hours and booking rules, and a live-calendar mode is optional. The standard is a draft, version 0.1. It makes one claim: an assistant that reads the file and the tools gives correct answers where a web page alone leaves it guessing. That claim is being tested, and the results are pending.

If you are a client

Your site already does this. We run client sites on their own domains. Each one publishes the file at /.well-known/open-service-profile at Level 2, but only when its facts are complete. A site missing a required fact publishes nothing rather than a placeholder. Those sites answer the three read tools. Booking requests run through the schedule page. Coverage is the exact ZIP list from the site's own service-area pages, not a radius. Here is a live one: coastalecoheatair.com/.well-known/open-service-profile

If your site is not with us, our parent company offers a free generator that drafts this file and your llms.txt from your own website, and marks anything your pages do not state as a line for you to complete. Generate your Open Service Profile.

Read the standard

Our parent company publishes the standard. The text is free to reuse with credit (CC BY 4.0). The schemas and code are open source (MIT). The standard covers how an assistant finds the file, what the file holds, all six tools, the rules for customer consent and record-keeping, and a checklist for each level.

Read Open Service Profile v0.1

Open Service Profile for HVAC | The HVAC Marketing Guys