---
title: "Hosted"
description: "Use mordn-hosted persistence, storage, configuration, and feedback from a server-side API key."
---

The hosted backend replaces your chat database and attachment bucket with
`@mordn/chat-api`. The API key authenticates a tenant and agent; the handler's
verified `userId` scopes each end-user request.

## createMordnHandler

One key wires published config, persistence, storage, and feedback. This is
the recommended setup.

```ts title="app/api/chat/[[...chat]]/route.ts"
import { createMordnHandler } from '@mordn/chat-widget/server';
import { auth } from '@clerk/nextjs/server';

export const { GET, POST, DELETE, OPTIONS } = createMordnHandler({
  apiKey: process.env.MORDN_CHAT_KEY!,
  getUserId: async () => (await auth()).userId,
});
```

```env
MORDN_CHAT_KEY="mck_live_..."
```

Every other `createChatHandler` option is accepted alongside `apiKey` and
`getUserId`, so you can add `buildTools`, `cors`, or knowledge without giving
up the hosted wiring.

## Wiring the pieces yourself

`createMordnHandler` composes these four clients. Use them directly when you
want to mix hosted and self-hosted parts — for example hosted config with
your own Postgres store.

```ts
import {
  createHostedChatStore,
  createHostedStorage,
  createHostedConfig,
  createHostedFeedback,
} from '@mordn/chat-widget/server/hosted';

const hosted = { apiKey: process.env.MORDN_CHAT_KEY! };

export const { GET, POST, DELETE } = createChatHandler({
  getUserId: getChatUserId,
  store: createHostedChatStore(hosted),
  storage: createHostedStorage(hosted),
  getHostedConfig: createHostedConfig(hosted),
  onFeedback: createHostedFeedback(hosted),
});
```

`baseUrl` defaults to `https://api.mordn.com`; `timeoutMs` defaults to 30 seconds.
The key is server-only.

## Hosted configuration precedence

`createHostedConfig` caches per-user results in process for 60 seconds and
returns `null` on failure. The current normalized fields include model, system
prompt, greeting, appearance, max output tokens, and follow-ups.

- Model: code, then hosted config, then an error.
- System prompt: code, then hosted config, then the package generic prompt.
- Output cap: code, then hosted config, then provider default.
- Follow-ups: code, then hosted config, then off.

> **Warning**
>
> A control-plane failure is harmless only when required code fallbacks exist. If
> you omit `model` and hosted configuration is unavailable or has no model, the
> turn fails because there is no package-default model.

## Store behavior

The hosted store implements ownership-scoped conversation and message
persistence. Its current `listMessages` implementation fetches the complete
conversation and ignores `limit`/`before`; do not promise infinite-scroll
pagination until the hosted API/store implements it.

Hosted storage provides upload, re-sign, and removal over the same tenant and
verified-user axes.
