Husly Rentals partner API

Version 1.0.0. Machine-readable: openapi.json

For travel agencies, channel managers and AI travel agents that sell one Husly rental business's cars, bikes, boats, gear or places to stay.

The business makes your key under Rentals > Integrations > Partner API. A key opens ONE site: its published catalogue and the bookings you made.

Prices are integer cents. Times are UTC instants; a pick (from, to) is a date in the listing's own time zone.

A booking you make is never paid on Husly: you settle with the renter. The business confirms it, or it is confirmed at once when the listing or your key says so.

Holds: hold: true keeps the dates 20 minutes (at most 60) and tells nobody; POST /bookings/{id}/confirm books them. An unconfirmed hold lets the dates go by itself.

Limits: 120 requests a minute and 60 new bookings an hour per key.

MCP: the same API as a Model Context Protocol server at POST /api/partner/v1/rentals/mcp (Streamable HTTP, JSON answers, protocol 2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26), with the same key.

Webhooks: every POST carries X-Husly-Event, X-Husly-Timestamp and X-Husly-Signature: sha256=<hex>, the HMAC-SHA256 of <timestamp>.<body> with your secret.

Start

curl -H "Authorization: Bearer hsly_partner_..." https://api.husly.app/api/partner/v1/rentals/me

Endpoints

GET/api/partner/v1/rentals/meYour key, the site and its terms
Answers: 200, 401, 403, 429
GET/api/partner/v1/rentals/listingsThe published catalogue
With from and to only the listings free on those days are kept.
  • category (query): A category slug.
  • from (query): First day, YYYY-MM-DD.
  • to (query): Last day, YYYY-MM-DD.
Answers: 200, 400, 401, 403, 404, 429
GET/api/partner/v1/rentals/listings/{slug}One listing
  • slug (path, required): The listing's slug.
Answers: 200, 401, 403, 404, 429
GET/api/partner/v1/rentals/listings/{slug}/calendarFree and taken days
  • slug (path, required): The listing's slug.
  • from (query): First day, YYYY-MM-DD. Default today.
  • days (query): How many days, 1 to 62. Default 31.
Answers: 200, 400, 401, 403, 404, 429
GET/api/partner/v1/rentals/listings/{slug}/quotePrice and availability for a range
  • slug (path, required): The listing's slug.
  • from (query, required): YYYY-MM-DD, or YYYY-MM-DDTHH:MM for a rental priced by the hour, in the listing's time zone.
  • to (query, required): YYYY-MM-DD, or YYYY-MM-DDTHH:MM for a rental priced by the hour, in the listing's time zone.
  • extras (query): Add-ons as id:qty,id:qty.
Answers: 200, 400, 401, 403, 404, 429
GET/api/partner/v1/rentals/bookingsYour bookings
  • status (query): held, pending, confirmed, cancelled, expired, completed or noshow.
  • reference (query): Your own reference.
  • limit (query): 1 to 100. Default 50.
  • offset (query): Default 0.
Answers: 200, 401, 403, 429
POST/api/partner/v1/rentals/bookingsBook, or hold the dates
Answers: 200, 201, 400, 401, 403, 404, 409, 422, 429
GET/api/partner/v1/rentals/bookings/{id}One of your bookings
  • id (path, required): The booking id.
Answers: 200, 401, 403, 404, 429
POST/api/partner/v1/rentals/bookings/{id}/confirmConfirm a hold
  • id (path, required): The booking id.
Answers: 200, 401, 403, 404, 409, 429
POST/api/partner/v1/rentals/bookings/{id}/cancelCancel a booking or let a hold go
  • id (path, required): The booking id.
Answers: 200, 401, 403, 404, 409, 429
GET/api/partner/v1/rentals/webhookYour webhook
Answers: 200, 401, 403, 429
PUT/api/partner/v1/rentals/webhookSet the address
The signing secret is in the answer when the webhook is new, or with rotate: true. Store it then.
Answers: 200, 201, 400, 401, 403, 429
DELETE/api/partner/v1/rentals/webhookRemove it
Answers: 200, 401, 403, 429
POST/api/partner/v1/rentals/webhook/testSend a ping
Answers: 202, 401, 403, 404, 429
POST/api/partner/v1/rentals/mcpThe MCP server (JSON-RPC 2.0)
Protocol 2026-07-28 (stateless: server/discover, tools/list, tools/call, with MCP-Protocol-Version, Mcp-Method and Mcp-Name headers) and 2025-03-26 to 2025-11-25 (initialize, ping, tools/list, tools/call). One message per request; a notification gets 202.
Answers: 200, 202, 401, 403, 429
GET/api/partner/v1/rentals/openapi.jsonThis document
Answers: 200
GET/api/partner/v1/rentals/docsThis document as a page
Answers: 200

Book with a hold

Hold first, show the guest the price and the terms, then confirm.

POST https://api.husly.app/api/partner/v1/rentals/bookings
{
  "listing": "city-bike",
  "from": "2026-11-06",
  "to": "2026-11-08",
  "guest": { "name": "Mari Maasikas", "email": "[email protected]", "phone": "+372 5555 5555" },
  "termsAccepted": true,
  "locale": "en",
  "hold": true,
  "reference": "AG-10442"
}

POST https://api.husly.app/api/partner/v1/rentals/bookings/{id}/confirm

MCP for AI agents

Add the server to an MCP client that can send a header. The tools are search_rentals, get_rental, get_rental_calendar, quote_rental, book_rental, confirm_booking, cancel_booking, get_booking, list_bookings and rentals_site_info. A read-only key gets no booking tools.

{
  "mcpServers": {
    "husly-rentals": {
      "type": "http",
      "url": "https://api.husly.app/api/partner/v1/rentals/mcp",
      "headers": {
        "Authorization": "Bearer hsly_partner_..."
      }
    }
  }
}

Webhook signature

// Node: check a webhook before you trust it.
const crypto = require("node:crypto");
function verify(rawBody, headers, secret) {
  const ts = headers["x-husly-timestamp"];
  const sig = (headers["x-husly-signature"] || "").replace(/^sha256=/, "");
  const want = crypto.createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && sig.length === want.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(want));
}