---
name: "maison-hubspot"
description: "Link Maison hotels to companies in Maison's own HubSpot portal: search companies, read a hotel's link and last push outcome, link by id or create-and-link in one call, unlink, and push the last week's chat volume. Use for Maison's internal CRM upkeep; these tools are absent when HubSpot is switched off in the environment. Tools: get_hubspot_link, link_hubspot_company, push_hubspot_chat_volume, search_hubspot_companies, unlink_hubspot_company."
license: "Proprietary. Use with a Maison API key under the Maison terms of service."
metadata:
  author: "maison-labs"
  version: "1.0.0"
  category: "hubspot"
  api-base: "https://maison-labs.com"
  openapi: "https://maison-labs.com/api/v1/openapi.json"
  docs: "https://docs.maison-labs.com/skills/maison-hubspot/"
---

# Maison — HubSpot company links (Maison staff)

Link Maison hotels to companies in Maison's own HubSpot portal: search companies, read a hotel's link and last push outcome, link by id or create-and-link in one call, unlink, and push the last week's chat volume. Use for Maison's internal CRM upkeep; these tools are absent when HubSpot is switched off in the environment.

Part of the Maison public API. Read the `maison-public-api` skill first for authentication, discovery and transport details (`https://docs.maison-labs.com/skills/maison-public-api/SKILL.md`).

## When to use

- Keep CRM records in sync after onboarding a hotel — `link_hubspot_company`.

## Before you start

1. Send `x-api-key: <key>` on every call; the key only reaches `/api/v1`.
2. `GET /api/v1/tools` (or MCP `tools/list`) returns the tools THIS key may run — if a tool below is missing there, you lack a grant; do not retry it.
3. Client-scoped tools take `clientId` (a hotel id). `whoami` lists the ids you can act on.

## Tools

| Tool | What it does | REST | Needs |
| --- | --- | --- | --- |
| `get_hubspot_link` | Return the client's HubSpot company mapping and the last push outcome. | `GET /api/v1/client/{clientId}/hubspot` | hubspot READ (global); read-only |
| `link_hubspot_company` | Link a client to a HubSpot company, or create a new one and link it. | `PUT /api/v1/client/{clientId}/hubspot` | hubspot WRITE (global) |
| `push_hubspot_chat_volume` | Push this week's chat-volume metric to the client's linked HubSpot company. | `POST /api/v1/client/{clientId}/hubspot/push` | hubspot EXECUTE (global) |
| `search_hubspot_companies` | Search Maison's HubSpot portal for companies by name or domain. | `GET /api/v1/hubspot/companies` | hubspot READ (global); read-only |
| `unlink_hubspot_company` | Remove the client's HubSpot company mapping. | `DELETE /api/v1/client/{clientId}/hubspot` | hubspot WRITE (global); destructive |

Full input fields for every tool: [references/tools.md](references/tools.md).

## Recommended workflows

### Link a hotel

1. `search_hubspot_companies` with the hotel name or domain.
2. `link_hubspot_company` with `hubspotCompanyId` (or `create: { name, domain }` when none exists).
3. `push_hubspot_chat_volume` with `dryRun: true` to preview, then without.

## Tips

- `get_hubspot_link` reports the outcome of the last weekly push.

## Pitfalls

- A 409 from `link_hubspot_company` means the company is already linked to another hotel, or a company was created but the link failed (the id is in `details`).
- 503 means HubSpot is not configured in this environment.

## Calling conventions

Same tool, three transports — pick whichever your runtime already speaks. Always send `x-api-key`.

```bash
# REST
curl -X GET "https://maison-labs.com/api/v1/client/<clientId>/hubspot" -H "x-api-key: $MAISON_API_KEY"
```

```json
// MCP (https://maison-labs.com/mcp, Streamable HTTP): tools/call
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_hubspot_link", "arguments": {} } }
```

```json
// A2A (https://maison-labs.com/a2a): tasks/send with a data part
{ "jsonrpc": "2.0", "id": 1, "method": "tasks/send", "params": { "message": { "role": "user", "parts": [{ "type": "data", "data": { "tool": "get_hubspot_link", "input": {} } }] } } }
```

Errors are the same everywhere: `401` no/invalid key; `403 forbidden` with `details.missing` (the grants you lack — fall back to the composite's parts or stop); `403 not_entitled` (the hotel's plan lacks the feature); `404`, `409`, `413 too_large`, `503`. Inputs that fail validation return `400 invalid_input` with the Zod issues — fix and retry once.
