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-Keyheader, or asAuthorization: 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 inRetry-After. On503, 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.
| Endpoint | Purpose |
|---|---|
GET /v1/service-area?zip=92101 | Coverage for a five-digit US ZIP string. |
GET /v1/services | Supported service IDs, names, billing periods, visit frequency and allowed modifiers. |
POST /v1/estimate | Indicative 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: requireszip.list_services: takes an empty object.estimate_pool_service: requireszipandserviceId; accepts optionalmodifiers.
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 status | What your app should show |
|---|---|
estimate | total is an indicative USD amount. base and additions explain the total. |
out_of_area | The ZIP is outside the tool's current coverage. No price is returned. |
manual_quote | Cabana needs to review the work before pricing it. No price is returned. |
unavailable | The 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.