The short answer

There are two ways to connect Duve to Claude. First, Duve's developer hub runs an official MCP server at developers.duve.com/_mcp/server, built for AI clients like Claude Code; it gives Claude live access to Duve's API documentation and takes about two minutes with no approval required. Second, Duve's Open API can feed real account data (guest links, chat activity, webhooks) into Claude through a small MCP server you run yourself, but credentials are not self-serve: they come through Duve's integration onboarding, which starts with an email to Duve's partnerships team. This guide covers both paths in order.

Two connection paths

Most platforms in this series have a self-serve API key buried in a settings page. Duve is different: the documentation is radically open (every docs page has a clean Markdown version and the whole hub is indexed for AI agents), while data credentials are relationship-gated. So the honest map looks like this:

Works today

Duve's official docs MCP

Hosted by Duve at developers.duve.com/_mcp/server. Claude gets live, searchable access to the Duve API reference, guides, and webhook appendices.

  • No Duve account needed
  • No approval, no keys
  • Docs only, never your guest data
Needs onboarding

Open API wrapped as MCP

OAuth2 client-credentials API for reading data out of Duve: accounts, guest links, last chat message, webhook management. You wrap it in a ~90-line Node server.

  • Credentials via Duve's integration team
  • Sandbox first, then production
  • Real reservation-level data in Claude

What a guest experience manager can ask

With the docs MCP connected, Claude becomes a Duve integration expert. With the Open API connected too, it can touch live reservations. Real prompts:

"Which Duve webhook events fire during online check-in? I want to trigger our turnover checklist when pre-check-in completes."Docs MCP
"Write the exact request to create a Duve webhook that posts to our endpoint when an upsell order is created."Docs MCP
"Guest in reservation HTL-20441 says they never got their check-in link. Pull their Duve guest app and online check-in URLs."Open API
"What was the last message in the Duve chat for reservation 88213, who sent it, and has it been read?"Open API
"List every webhook currently registered on our Duve company and flag any pointing at endpoints we've retired."Open API
Path 1 · No approval needed

Connect Duve's docs MCP server

Duve's own developer hub says it plainly: "For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.duve.com/_mcp/server." It is a documentation server, so Claude can search and read the entire Duve API reference in place instead of you pasting pages into chat.

1

Add it to Claude Code (one command)

Terminal
claude mcp add --transport http duve-docs https://developers.duve.com/_mcp/server

That's it. Open a Claude Code session and ask a Duve API question; Claude will pull the answer from Duve's live docs.

2

Or add it to Claude Desktop / claude.ai as a connector

  1. Open Settings → Connectors in Claude Desktop or claude.ai.
  2. Click Add custom connector.
  3. Name it Duve Docs and paste https://developers.duve.com/_mcp/server as the URL.
  4. Save. No sign-in step, the docs are public.

Bonus trick even without MCP: append .md to any page URL on developers.duve.com and you get clean Markdown, and the full docs index lives at developers.duve.com/llms.txt. Paste either straight into any AI tool.

Try it

"Using the Duve docs, list every webhook event key related to orders and upsells, and show me the request body to create a webhook for orderCreated."
Path 2 · Live account data

Wrap the Duve Open API for Claude

Duve documents three API surfaces on its developer hub: a PMS API (for property management systems pushing reservations into Duve), DuveConnect (operational partners), and the Open API, which is the one that reads data out and the one we want. It uses OAuth2 client credentials, is rate-limited to 60 requests a minute, and issues bearer tokens that expire after one hour.

The published Open API surface is deliberately small: an accounts list, per-account tokens, a GuestLink endpoint (guest app link, chat link, online check-in link, and optionally the last chat message for any reservation, looked up by its PMS reservation ID), and full webhook management. Small, but it covers the question your front desk actually asks every day: "did this guest get their link, and what was the last thing said in the chat?"

1

Get credentials from Duve

There is no API keys page in the Duve dashboard. Duve's developer hub describes a four-stage onboarding:

  1. Email Partners@duve.com for business onboarding (NDA and agreements).
  2. Work with Integrations@duve.com on the technical setup. You develop against Duve's sandbox environment (sandbox.duve.com), which replicates production with test data.
  3. Duve's core team validates the integration in production.
  4. The business development team finalizes the partnership.

If you are an existing Duve customer rather than a vendor, the Open API reference says to create a sync source of type Duve Open API in your account, and to contact the integration team if that source type is not available to you. Either way you end with a client_id and client_secret.

2

Set up the Node.js project

Terminal
mkdir duve-mcp
cd duve-mcp
npm init -y
npm install @modelcontextprotocol/sdk zod

Add "type": "module" to package.json:

package.json
{
  "name": "duve-mcp",
  "version": "1.0.0",
  "type": "module",
  "main": "index.js",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.0",
    "zod": "^3.22.0"
  }
}
3

Create the MCP server file

Save this as index.js. Three read-only tools: get-guest-links, list-accounts, and list-webhooks. Because Duve tokens expire after an hour, the server mints and caches its own token and refreshes automatically.

index.js
#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const CLIENT_ID = process.env.DUVE_CLIENT_ID;
const CLIENT_SECRET = process.env.DUVE_CLIENT_SECRET;
// Sandbox by default. Swap for the production URL Duve
// gives you at certification.
const BASE_URL = process.env.DUVE_API_URL || "https://sandbox.duve.com";

if (!CLIENT_ID || !CLIENT_SECRET) {
  console.error("Missing DUVE_CLIENT_ID or DUVE_CLIENT_SECRET");
  process.exit(1);
}

// --- Token cache: Duve access tokens expire after 1 hour ---
let cachedToken = null;
let tokenExpiresAt = 0;

async function getToken() {
  if (cachedToken && Date.now() < tokenExpiresAt - 60_000) {
    return cachedToken;
  }
  const response = await fetch(`${BASE_URL}/api/openapi/v1/oauth2/token`, {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
      client_id: CLIENT_ID,
      client_secret: CLIENT_SECRET,
      grant_type: "client_credentials",
    }),
  });
  if (!response.ok) {
    throw new Error(`Duve token request failed: ${response.status}`);
  }
  const data = await response.json();
  cachedToken = data.access_token;
  tokenExpiresAt = Date.now() + (data.expires_in || 3600) * 1000;
  return cachedToken;
}

async function duveGet(path, params = {}) {
  const token = await getToken();
  const url = new URL(`${BASE_URL}/api/openapi/v1${path}`);
  for (const [key, value] of Object.entries(params)) {
    if (value !== undefined && value !== null && value !== "") {
      url.searchParams.append(key, String(value));
    }
  }
  const response = await fetch(url.toString(), {
    headers: {
      Authorization: `Bearer ${token}`,
      Accept: "application/json",
      "User-Agent": "rapideye-duve-mcp/1.0",
    },
  });
  if (!response.ok) {
    const body = await response.text();
    throw new Error(`Duve API ${response.status}: ${body}`);
  }
  return response.json();
}

const server = new McpServer({ name: "duve", version: "1.0.0" });

// Tool 1: Guest links + last chat message for a reservation
server.tool(
  "get-guest-links",
  "Fetch the Duve guest app link, chat link, and online check-in link for a reservation, looked up by its PMS reservation ID (externalId) or CRS reservation ID. Optionally includes the last message in the guest chat with author, timestamp, and channel.",
  {
    externalId: z
      .string()
      .optional()
      .describe("The PMS reservation ID (provide this or crsExternalId)"),
    crsExternalId: z
      .string()
      .optional()
      .describe("The CRS reservation ID (provide this or externalId)"),
    includeLastMessage: z
      .boolean()
      .optional()
      .describe("Also return the last message sent in the guest's chat"),
  },
  async ({ externalId, crsExternalId, includeLastMessage }) => {
    const data = await duveGet("/reservations/links", {
      externalId,
      crsExternalId,
      includeLastMessage: includeLastMessage ? 1 : undefined,
    });
    return {
      content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
    };
  }
);

// Tool 2: List accounts under the credential
server.tool(
  "list-accounts",
  "List the Duve accounts this credential can access. Use this first when the credential covers multiple properties or brands.",
  {},
  async () => {
    const data = await duveGet("/accounts");
    return {
      content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
    };
  }
);

// Tool 3: List registered webhooks
server.tool(
  "list-webhooks",
  "List all webhooks registered on the Duve company: their events, target URLs, and conditions. Read-only; use it to audit what automations currently fire.",
  {},
  async () => {
    const data = await duveGet("/webhooks");
    return {
      content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

Want more? Every remaining endpoint (account tokens, webhook create/update/delete) is in the Open API reference, and if you did Path 1, Claude can read that reference itself and extend this file for you. We kept writes out on purpose: a webhook Claude can list is useful, a webhook Claude can delete is a risk.

4

Register the server with Claude Desktop

Open your Claude Desktop config file:

macOS path
~/Library/Application Support/Claude/claude_desktop_config.json
Windows path
%APPDATA%\Claude\claude_desktop_config.json

Add the Duve entry (merge into your existing mcpServers block if you've set up other guides from this series):

claude_desktop_config.json
{
  "mcpServers": {
    "duve": {
      "command": "node",
      "args": ["/absolute/path/to/duve-mcp/index.js"],
      "env": {
        "DUVE_CLIENT_ID": "your_client_id",
        "DUVE_CLIENT_SECRET": "your_client_secret",
        "DUVE_API_URL": "https://sandbox.duve.com"
      }
    }
  }
}

Replace the path and credentials, then fully quit and reopen Claude Desktop. When Duve certifies you for production, change DUVE_API_URL to the production base URL they provide.

Try it

"Look up reservation TEST-1001 in Duve with the last chat message included, and tell me whether the guest has opened their online check-in link's chat."

The webhook events worth knowing

Even before you touch the Open API, Duve's webhook catalog is the thing to study, because it maps the whole guest journey. A few of the 20+ documented event keys:

Event keyFires when
reservationCreatedA reservation lands in Duve
preCheckInDoneThe guest completes online check-in
guestDocumentUploadedThe guest uploads an ID document
orderCreatedAn upsell order is placed
orderRefundedAn order is refunded
messageSentA chat message is sent
reservationRoomAssignA room is assigned to the reservation
preCheckOutDoneThe guest completes online check-out

Per Duve's developer FAQ, webhooks typically deliver within seconds (up to 30 minutes worst case), and failed deliveries are retried up to two times within an hour before being marked failed. Design your receiving endpoint to be idempotent: the FAQ also notes Duve may send two webhooks for the same reservation update.

Troubleshooting

401 Unauthorized partway through a session

Duve access tokens expire after one hour. The server above caches the token and re-mints it a minute before expiry; if you wrote your own and hardcoded a token, that's the bug. Also confirm the token request is sent as application/x-www-form-urlencoded with grant_type=client_credentials.

429 Too Many Requests

The Open API is limited to 60 requests a minute. Claude can burst past that when iterating over many reservations. Ask it to batch ("look these up one at a time, pausing between calls") or add a small delay in duveGet.

GuestLink returns nothing for my reservation ID

The lookup key is the PMS reservation ID (externalId) or the CRS reservation ID (crsExternalId), not Duve's internal ID. Use the exact ID as it appears in your PMS. One of the two parameters is required.

I don't have a client_id and client_secret

Duve Open API credentials are not self-serve. Vendors start with Partners@duve.com; existing customers should ask their Duve contact about enabling a Duve Open API sync source on the account. While you wait, Path 1 (the docs MCP) works immediately and needs nothing.

Claude doesn't see any Duve tools

Claude Desktop only reads the config file at startup. Fully quit Claude (Cmd+Q on macOS, right-click tray icon and Quit on Windows) and reopen it. Still broken? Check Help → Open Logs Folder for invalid JSON in the config, a wrong absolute path to index.js, or node missing from PATH.

The docs MCP connects but answers seem stale or partial

Fall back to the raw index: https://developers.duve.com/llms.txt lists every docs page, and appending .md to any page URL returns clean Markdown. Paste the specific page into the conversation and Claude will work from that.

Quick FAQ

Does Duve have a public API?

The documentation is public at developers.duve.com, covering a PMS API, DuveConnect, and the Open API. Credentials are not self-serve: access runs through Duve's partner onboarding (NDA, technical collaboration, sandbox certification, then production).

Does Duve have an MCP server?

Yes, for documentation. Duve's developer hub publishes an MCP endpoint at developers.duve.com/_mcp/server aimed at AI clients like Claude Code and Cursor. It serves Duve's API docs, not account data. No data MCP server is published; for live data you wrap the Open API yourself as shown above.

What is DuveAI, and is this the same thing?

No. DuveAI is Duve's guest-facing AI, launched in Q2 2023 on OpenAI's ChatGPT-4 according to Hotel Tech Report, handling guest messaging in over 100 languages across WhatsApp, SMS, email, guest apps, and OTA channels, with sentiment-based prioritization and upsell suggestions. Duve's site cites Edgar Suites automating 80% of guest inquiries with it. Connecting Duve to Claude is the operator-side complement: your team asking questions about your Duve setup and data.

How big is Duve?

According to Hotel Technology News, Duve raised a $60 million Series B led by Susquehanna Growth Equity in December 2025 ($85 million total), was founded in 2015, serves over 1,000 brands in more than 70 countries including Accor, OYO, and Leonardo Hotels, manages more than one million guest journeys per month, and maintains over 150 integrations with PMS, POS, mobile key, and operational systems including Mews, Cloudbeds, Opera, and Apaleo.

Can Claude send guest messages through Duve?

Not with this guide. The published Open API endpoints are read and webhook-management oriented (the GuestLink endpoint can read the last chat message, not send one), and the server here is deliberately read-only. Guest-facing automation is DuveAI's job inside the platform.

Where this fits in an ops stack

Duve owns the guest-facing journey: check-in, upsells, chat. The physical side of the same turnover, whether the unit is actually ready and undamaged before that check-in link goes out, is what RapidEye covers, by reading the photos and video your cleaners already capture. A preCheckInDone webhook on one side and an inspection verdict on the other is a genuinely good pairing.

Stuck on the setup, or want a guide for another platform in your stack? Browse the rest of the series at claude-guides or see the RapidEye API.


Sources & references

  1. Duve Developer Hub docs index (includes the MCP server endpoint for AI clients)https://developers.duve.com/llms.txt
  2. Welcome to the Duve Developer Hub (partner onboarding stages, sandbox environment)https://developers.duve.com/home/home/welcome-to-the-duve-developer-hub
  3. Duve Open API: Introduction (OAuth2 bearer auth, 60 req/min rate limit)https://developers.duve.com/api-references/open-api/introduction
  4. Duve Open API: Token (client credentials flow, 1-hour expiry)https://developers.duve.com/api-references/open-api/open-api/authorization/token
  5. Duve Open API: GuestLink (guest app, chat, check-in links, last message)https://developers.duve.com/api-references/open-api/open-api/reservations/guest-link
  6. Duve webhook event keys appendixhttps://developers.duve.com/api-references/open-api/appendix/webhook-events
  7. Duve developer FAQ (webhook delivery timing, retries, duplicates)https://developers.duve.com/guides/guides/faq
  8. Revolutionizing Guest Experience, Duve Introduces AI into Hospitality with 'DuveAI' (Hotel Tech Report)https://hoteltechreport.com/news/duve-ai
  9. Revolutionize Your Guest Experience With Duve Hospitality AI (Duve)https://duve.com/duve-ai/
  10. Duve Raises $60 Million to Scale Its Unified AI-Driven Hotel Guest Experience Platform Globally (Hotel Technology News)https://hoteltechnologynews.com/2025/12/duve-raises-60-million-to-scale-its-unified-ai-driven-hotel-guest-experience-platform-globally/
  11. Duve Integrationshttps://duve.com/integrations/
  12. Model Context Protocol TypeScript SDKhttps://github.com/modelcontextprotocol/typescript-sdk

Other guides

Or browse the full Claude guides index, 35+ platforms and counting.