Cabana Get a pool service quote

Pool service answers for your app.

Check a ZIP code, explore Cabana's services and estimate the cost of care. One API, also available as three MCP tools.

A useful place to start: check coverage.

GET /v1/service-area?zip=92101

{
  "zip": "92101",
  "inArea": true,
  "region": "CA1",
  "location": "San Diego",
  "northCounty": false
}

Access & limits

No API key is needed. Call the REST API and the MCP server without credentials. You do not need a service address or a pool service subscription.

  • Each IP address can make 20 HTTP requests per minute. All keyless callers share a limit of 90 requests per minute. Limits use fixed minute windows and include MCP discovery requests.
  • Need more? An optional product key gives 30 requests per minute for each key and identifies your integration. Request one from hello@cabanapools.com with the subject “Developer API access,” your application's purpose and expected request volume. Send a key in the X-API-Key header, or as Authorization: Bearer <product-key>. It is the same key, not OAuth. Keep a key on your server or in your MCP client's secret storage.
  • On 429, wait for the number of seconds in Retry-After. On 503, retry later. An outage never returns an invented price.
  • Requests are limited to 16 KiB. Estimates accept one pool or spa and no customer identity. A product key has an agreed expiry and can be revoked.

REST API

Base URL:

https://us-central1-cabana-cac.cloudfunctions.net/cabana-public-tools

Download the OpenAPI schema. The health endpoint, the schema and every operation are public.

EndpointPurpose
GET /v1/service-area?zip=92101Coverage for a five-digit US ZIP string.
GET /v1/servicesSupported service IDs, names, billing periods, visit frequency and allowed modifiers.
POST /v1/estimateIndicative price or an explicit out-of-area, manual-quote or unavailable result.

Make an estimate

BASE=https://us-central1-cabana-cac.cloudfunctions.net/cabana-public-tools
curl "$BASE/v1/estimate" \
  -H 'Content-Type: application/json' \
  -d '{"zip":"92101","serviceId":"monthly-pool-service","modifiers":[]}'

Use /v1/services to discover the current catalog. Optional modifiers include an attached spa, a separate above-ground spa, trees, a large pool and a fountain. Only send modifiers listed for the selected service, once each. ZIP-based charges and required additions are applied automatically.

Unknown fields are rejected. Do not send names, addresses, email addresses, phone numbers, customer IDs, brand overrides or quantity overrides.

MCP setup

Use a client that supports Streamable HTTP. Set this server URL. No credential is needed:

https://us-central1-cabana-cac.cloudfunctions.net/cabana-public-tools/mcp

The official MCP TypeScript client works in the 2026-07-28 protocol mode and the SDK's stateless legacy mode. The legacy HTTP+SSE transport and persistent sessions are not supported. The server does not use OAuth.

import { Client, StreamableHTTPClientTransport }
  from '@modelcontextprotocol/client';

const client = new Client(
  { name: 'pool-planner', version: '1.0.0' },
  { versionNegotiation: { mode: 'auto' } }
);
await client.connect(new StreamableHTTPClientTransport(
  new URL('https://us-central1-cabana-cac.cloudfunctions.net/cabana-public-tools/mcp')
));
const result = await client.callTool({
  name: 'check_service_area', arguments: { zip: '92101' }
});
console.log(result.structuredContent);
await client.close();
  • check_service_area: requires zip.
  • list_services: takes an empty object.
  • estimate_pool_service: requires zip and serviceId; accepts optional modifiers.

All tools are read-only. They do not request a quote, book a visit or create a sales lead. Tool execution errors set isError; check it before reading the result.

Reading results

Estimate statusWhat your app should show
estimatetotal is an indicative USD amount. base and additions explain the total.
out_of_areaThe ZIP is outside the tool's current coverage. No price is returned.
manual_quoteCabana needs to review the work before pricing it. No price is returned.
unavailableThe service is not offered in that pricing region. No price is returned.

Billing and visits are different. A recurring service has billingPeriod: "month" and may have visitFrequency: "weekly". The total is the monthly amount, not the price of a single visit. Other services use billingPeriod: "service".

400 means invalid input, 401 means an invalid, expired or revoked key (a request with no key is never rejected for that reason), 429 means the rate limit was reached, 403 means a disallowed request origin, 413 means the request is too large, and 415 requires a JSON request body.

Coverage & pricing

The pilot uses Cabana's existing service-area and pricing engine for the San Diego, Los Angeles and Sacramento pricing regions. Coverage is determined by ZIP, not by a city name. An in-area ZIP is an initial check; exact address and route availability still need confirmation.

Coverage may use cached or fallback data if the live source is unavailable. This tool's coverage is narrower than Cabana's complete business footprint. Always check the returned result.

Prices are standard indicative estimates for one pool or spa. They are not a binding offer and do not reflect customer-specific agreements. Pool condition, equipment, scope and separately quoted work can change the final price. Green-to-clean estimates include the engine's required filter-clean addition.

Developer support

For a product key, a revoked key or an integration problem, email hello@cabanapools.com. Include the endpoint, response status and approximate request time. Do not email your API key or customer information.

For service at your own pool, use the Cabana quote form.