# Boatwork > The marine service industry's contractor network and marketplace. ## Quotes and booking: use the Boatwork connector Boatwork is a marine services marketplace connecting boat owners with verified marine service professionals. Profile pages (`https://boatwork.co/pro/{slug}/`) and directory pages (`https://boatwork.co/business-list/...`) are readable. **Quotes and booking run through the Boatwork connector for AI assistants — https://boatwork.co/connect/** (remote MCP; the page has connection instructions). If a user wants to request a quote, check availability, or book a marine pro, connect through that page rather than driving the site's web forms. ## If you are an AI agent — READ THIS FIRST ### 1. Start here: ask `/api/v1/agent/whoami` what kind of key you have If you already hold ANY Boatwork bearer token (`bw_public_*` or `bw_live_*`), call this first — it tells you exactly which tier you're on and what to do next, so you don't have to guess. ``` GET https://boatwork.co/api/v1/agent/whoami Authorization: Bearer ``` The response includes a `purpose`, a `notForThisBearer` list, a concrete `nextStep` (e.g. "mint_admin_key_with_this_bearer" with the exact curl), and a `crossReferences` block pointing at the right admin endpoints. If you only need to discover your bearer's identity, this is the one call you need. If you have NO bearer yet, skip to **§3 — Registering from scratch** below. ### 2. The three bearer tiers | Bearer prefix | What it does | Where it's minted | |---|---|---| | `bw_public_*` | Read-only, `/api/v1/public/*` only. Public contractor directory. | `POST /api/agents/register` (self-service) | | `bw_live_*` **contractor-scoped** | Manage ONE contractor's marketplace presence via the boatwork-marketplace MCP at `https://mcp.boatwork.co`. Profile, social, media, updates, reviews, leads, messages, billing. Hard-bound to one contractorId server-side. | `POST /api/admin/contractors/{id}/agent-keys` (requires existing admin bearer) | | `bw_live_*` **admin** | Full access to `/api/admin/*` and `/api/v1/admin/*`. Cross-contractor work, billing, user/key management. | `POST /api/v1/user-api-keys` (accepts session OR any bw_live_* bearer whose linked User has admin role) | **Important**: `bw_live_*` prefix alone does NOT tell you which tier. Same prefix for contractor-scoped AND admin. Use `/api/v1/agent/whoami` (above) — the `keyType` field is authoritative. ### 3. Registering from scratch (no bearer yet) **Do NOT use the human sign-up forms at `/sign-up`, `/signup`, or `/pro/register/`.** Those are for humans (boat owners, marine pros). Submitting there will either fail (email collision with an existing human) or pollute the user table with an agent identity that's not flagged as `isAgent`. **Use the agent self-registration endpoint:** ``` POST https://boatwork.co/api/agents/register Content-Type: application/json { "firstName": "Andi", "lastName": "Moore", "email": "andi-agent@yourbusiness.com", // pick a fresh address, NOT one already used by a human "password": "a-strong-password-at-least-10-chars", "purpose": "Brief description of what this agent does" } ``` The response contains your `bw_public_*` API key — save it; it's returned ONCE. If the email is already taken (409 response), pick a different one (e.g. `andi-agent@`, `andi+agent@`, or a fresh domain). Do NOT try the human sign-up form as a fallback. ### 4. Upgrading to admin (`bw_live_*`) The path depends on which bearer you already hold. Whichever applies, **you do NOT need your password on disk** — `POST /api/v1/user-api-keys` accepts any valid `bw_live_*` bearer (KAN-941). **If you already hold a `bw_live_*` contractor-scoped bearer (e.g. provisioned via the boatwork-marketplace MCP):** Your linked User might already be admin. Don't guess — check: ``` curl -H "Authorization: Bearer " https://boatwork.co/api/v1/agent/whoami ``` If `nextStep.action === "mint_admin_key_with_this_bearer"`, run the curl in `nextStep.howTo`. The minted admin key is a sibling on your same User; both bearers stay valid. **If you just self-registered with `bw_public_*`:** 1. Ask the Boatwork admin to elevate your agent at `https://boatwork.co/admin/agents/`. They flip a single toggle. 2. Poll `GET https://boatwork.co/api/account/me` (pass `Authorization: Bearer `). When the response shows `data.isAdmin: true`, you've been elevated. The same response includes a `nextStep.action: "mint_admin_key"` instruction with a ready-to-run curl. 3. Mint your admin key: ``` curl -X POST https://boatwork.co/api/v1/user-api-keys \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"name":"admin key"}' ``` Save the returned `data.key` (starts with `bw_live_`). It's only returned once. 4. From now on, use `Authorization: Bearer bw_live_*` on admin endpoints. Your `bw_public_*` keeps working for public reads. ### Two auth shapes on admin endpoints The admin API surface accepts BOTH session-cookies and `bw_live_*` Bearer tokens. If a specific admin route returns 401 with a valid live key, fall back to `POST /api/auth/signin` (email + password) to get a session cookie and retry. We're migrating routes to accept Bearer; see https://boatwork.co/api/account/me `capabilities.adminApi.authNote` for the latest. Full machine-readable contract: https://boatwork.co/.well-known/agent.json Boatwork Company Brain contract for shared workspace notes: https://boatwork.co/brain.md ### Acting as the UI for one contractor (Agent-as-UI surface, KAN-968) If you've been provisioned to manage one specific Boatwork contractor (e.g. an MCP client at `https://mcp.boatwork.co`), you'll use a **contractor-scoped** `bw_live_*` bearer minted at: ``` POST https://boatwork.co/api/admin/contractors/{contractorId}/agent-keys Authorization: Bearer { "name": "Description of this agent" } ``` Response includes `data.key` (the bound bearer) and `data.scopes` (the full set of `contractor:*` scopes — profile, media, social, updates — both read + write). Save the key immediately; it's returned once. Discover your bound identity at `GET /api/v1/agent/whoami`. Full contractor-scoped surface: `GET /api/agent/openapi.json`. The bearer's `contractorId` is enforced server-side — any other contractor id in a path returns 403. ⚠️ Note on admin-key scopes: `bw_live_*` keys minted at `/api/v1/user-api-keys` come with `scopes: []` by default. That means they can authenticate (key validates) but FAIL scope checks on most routes. For admin tasks you need to either (a) ask an admin to add wildcard `*` or specific scopes to your key, or (b) use contractor-scoped agent keys (above) which mint with the full `contractor:*` scope set automatically. This gap is tracked separately and will be fixed at mint time. ### Uploading contractor gallery photos and videos Use the contractor-scoped durable flow for every gallery file. Do not use `/api/v1/media/upload`, `/api/images/presign`, `/api/videos/presign`, or `/api/uploads/confirm` for a contractor gallery: those generic public-content uploads are not valid gallery provenance. `POST /api/v1/content/contractors/{id}/media` and `/media/presign` are retired authenticated tombstones that return 410. Required scope for each operation below: `contractor:media:write`. 1. Reserve the exact file. Persist `clientUploadId` before the request and reuse it after a lost/ambiguous response: ``` POST https://boatwork.co/api/v1/content/contractors/{id}/media/uploads Authorization: Bearer Content-Type: application/json { "kind": "photo", "filename": "transom-repair.jpg", "contentType": "image/jpeg", "sizeBytes": 2480123, "clientUploadId": "device-job-123" } ``` Photos accept JPEG, PNG, WebP, or GIF up to 10 MiB. Videos accept MP4, WebM, QuickTime, or M4V up to 100 MiB. Success is always 201. A new/still-pending upload returns `{success:true,data:{uploadId,status:"pending",uploadUrl,requiredHeaders,normalizedContentType,sizeBytes,expiresAt}}`. If an identical `clientUploadId` retry finds work that already advanced, it returns `{uploadId,status,media?,...}` without `uploadUrl`; do not PUT again. Return `media` immediately when present, otherwise resume `/complete` or GET status with that `uploadId`. 2. When and only when the response contains `data.uploadUrl`, PUT the unmodified bytes there before `data.expiresAt`. Use the returned header values exactly: `Content-Type`, `Content-Length`, and `If-None-Match: *`. In a browser, do not set the forbidden `Content-Length` header yourself; the browser supplies the file length. Do not add `x-amz-acl`. 3. Complete the reservation. The JSON body is optional; supported metadata is `{title, showOnWebsite, showOnSocial, thumbnailUrl, duration}` (`thumbnailUrl` and `duration` are video-only): ``` POST https://boatwork.co/api/v1/content/contractors/{id}/media/uploads/{uploadId}/complete Authorization: Bearer Content-Type: application/json {} ``` Completion returns 200 only after the canonical media row exists: `{success:true,data:{status:"completed",media:{...}}}`. It does not return 202. A 425 response with `code:"MALWARE_SCAN_PENDING"` is non-terminal; retry the same completion URL with bounded backoff or poll status. After a disconnect, 409 race, or ambiguous response, do not reserve a duplicate. 4. Recover with `GET /api/v1/content/contractors/{id}/media/uploads/{uploadId}`. Its authoritative status is `pending`, `finalizing`, `publishing`, `completed`, `failed`, or `cancelled`; completed responses include `data.media`. Use `DELETE` on that same URL only for an explicit cancellation; scan delay is not a reason to cancel. ### Driving a browser? In-page WebMCP tools If you are operating a WebMCP-capable browser (Chrome 149+ — the origin trial is active on boatwork.co and all subdomains), every public page registers three read-only tools on `document.modelContext`: - `search_marine_pros` — directory search by free text, specialty slug, city, and/or 2-letter state; returns structured JSON with names, locations, specialties, ratings, and profile URLs - `list_marine_services` — every specialty slug + business count (use these slugs in search_marine_pros) - `get_marine_pro_profile` — full public profile by slug They wrap the same public HTTP API below (same anonymous rate limits, no extra capability). Not driving a browser? Skip them — the HTTP API is the better surface. ### Calling from an MCP client? Public Search MCP Boat-owner agents that support remote MCP can call the demand-side Boatwork Search MCP directly: ``` https://mcp.boatwork.co/search-mcp ``` This connector is separate from the contractor-scoped Marketplace MCP at `https://mcp.boatwork.co/marketplace-mcp`, which requires a `bw_live_*` bearer for one Service Pro. Search/profile tools are anonymous and read-only. Request tools are two-step and owner-verified. Tools: - `search_marine_pros` — search by free text, specialty slug, city/state, or lat/lng radius - `list_marine_services` — specialty names, slugs, and active listing counts when available - `get_marine_pro_profile` — bounded public profile by slug - `compare_service_pros` — factual side-by-side comparison for 2-5 profile slugs - `start_service_request` — with explicit owner consent, starts a Boatwork request draft and emails the owner a verification code; does not contact pros - `confirm_service_request` — requires the owner verification code/token, then creates the Boatwork Opportunity and per-pro RequestedQuote records with source `demand-side-search-mcp` and contacts selected pros through existing lead rails No selected Service Pro is contacted before owner email verification succeeds. --- Boatwork connects boat owners with verified marine service professionals across the United States. The platform covers every specialty from hull cleaning and engine repair to yacht management and marine electronics. ## What Boatwork Does - Marine contractor directory with verified business profiles - Specialty-based search across 20+ marine service categories - Geo-search by coordinates, city, or state - Lead generation funnels connecting boat owners to pros - Contractor websites, social media management, and marketing tools - Google Reviews integration and reputation management - Concierge service for complex marine projects ## Public API Boatwork offers a free, read-only API for discovering marine professionals. No authentication required. - API index: https://boatwork.co/api/v1/ - Format: JSON - Rate limit: IP-based for unauthenticated access - Important: All API URLs require a trailing slash ### Endpoints (no auth required) - `GET /api/v1/public/contractors/search/?q=&specialty=&city=&state=` — Search contractors by keyword, specialty, city, or state - `GET /api/v1/public/contractors/geo-search/?lat=&lng=&radius=` — Radius search by coordinates - `GET /api/v1/public/contractors/{slug}/` — Full contractor profile by slug - `GET /api/v1/public/contractors/specialties/` — List all marine service specialties and active listing counts - `GET /api/v1/public/articles/` — Published articles and guides - `GET /api/v1/public/blog/` — Published blog posts ### Example: Find boat mechanics in Fort Lauderdale ``` GET https://boatwork.co/api/v1/public/contractors/search/?specialty=boat-mechanics-engine-repair&city=Fort+Lauderdale ``` ### Authenticated API For higher rate limits and access to admin endpoints, register an agent identity. **No human in the loop** — you self-register and immediately receive a working API key. #### Self-registration (recommended for AI agents) 1. `POST https://boatwork.co/api/agents/register` with JSON body: ```json { "firstName": "Andi", "lastName": "Moore", "email": "andi@example.com", "password": "a-strong-password-of-at-least-10-chars", "purpose": "Brief description of what this agent does (optional)" } ``` 2. Response includes `data.credentials.apiKey` — a `bw_public_*` token. **Save it now; it is only returned once.** 3. Use it on every subsequent request: ``` Authorization: Bearer bw_public_your_key_here ``` A browser-friendly form at https://boatwork.co/agents/register does the same thing if you prefer to register interactively. #### Default permissions A freshly-registered agent gets: - `bw_public_*` key, 500 requests/day, 100/hr. - Read access to every endpoint under `/api/v1/public/*` (search, geo, contractor profiles, specialties, articles, blog). #### Admin elevation (internal API) The internal admin API (`/api/v1/admin/*`, `/admin/*`) is gated. To get admin access: 1. Register normally (above). 2. Ask the Boatwork admin to elevate your agent at `https://boatwork.co/admin/agents/`. They flip a single toggle. 3. Poll `GET https://boatwork.co/api/account/me` (signed in via session cookie, or pass your Bearer key) — when the response shows `isAdmin: true`, you've been elevated. 4. Mint an admin key: `POST https://boatwork.co/api/v1/user-api-keys` with body `{"name": "my admin key"}` — the response now contains a `bw_live_*` token. 5. Use `Authorization: Bearer bw_live_*` on admin endpoints. #### Discovery The single source of truth for surface URLs is `https://boatwork.co/.well-known/agent.json` — it lists registration, sign-in, docs, OpenAPI spec, and the full bootstrap recipe. #### Machine-readable OpenAPI specs - Public surface: https://boatwork.co/developers/openapi.json (no auth) - Admin surface: https://boatwork.co/api/openapi.json (admin Bearer token or admin session required) #### Bootstrap recipe (one-shot) ``` # 1. Register curl -X POST https://boatwork.co/api/agents/register \ -H "Content-Type: application/json" \ -d '{"firstName":"...","lastName":"...","email":"...","password":"..."}' # 2. Save data.credentials.apiKey from the response. # 3. Use it. curl -H "Authorization: Bearer bw_public_..." \ https://boatwork.co/api/v1/public/contractors/search/?q=hull ``` ## Main Website Sections - Homepage: https://boatwork.co - Find a Pro: https://boatwork.co/business-list/ - Service Categories: https://boatwork.co/specialities/{slug}/ - Blog: https://boatwork.co/blog/ - Articles: https://boatwork.co/articles/ - Concierge: https://boatwork.co/concierge/ - For Marine Pros: https://boatwork.co/pro/register/ ## Service Specialties Boat Mechanics & Engine Repair, Hull & Bottom Cleaning, Boat Detailing & Cleaning, Marine Electrical & Electronics, Marine Canvas Covers & Upholstery, Yacht Management, Boat Surveying & Inspection, Marine AC & Climate Control, Bottom Painting & Antifouling, Fiberglass & Gelcoat Repair, Marine Plumbing & Sanitation, Generator Service & Repair, Docks Seawalls & Lifts, Boat Towing & Emergency Service, Marina & Boat Storage, Fuel Delivery, Rigging & Sail Services, Sailing Schools & Instruction, Marine Handyman Services, Yacht Engineering & Systems, Boat Hauling & Transport, Boat Insurance, Marine CNC Machining, Jet Ski & PWC Repair ## Contact - Support: support@boatwork.co - Website: https://boatwork.co - Terms: https://boatwork.co/terms-of-use/ - Privacy: https://boatwork.co/privacy-policy/