# Cossistant documentation URL: /docs ## Quickstart with your framework Start by selecting your framework of choice, then follow the instructions to install the dependencies and structure your app. Cossistant works with all React frameworks.
Next.js Next.js Add Cossistant {``} widget to your Next.js project. React React [soon] Add Cossistant {``} widget to any react compatible framework.
# What is Cossistant? URL: /docs/what **Own your support, either use our pre-built `` component, or build your own based on our headless components.** You know how most traditional support systems work: you load an external iframe and code within your app, making it harder to customize, use and even by time are being blocked by your users' ads blocker. This approach worked well until you need to customize your support and more recently, when you're trying to build AI agents that can truly be helpful with custom tools and logic. **You need control over the code to give true power to your agents.** This is what Cossistant aims to solve. It is built around the following principles: * **Open source:** You and the community can participate in making the tool safer and more powerful, no opaque black box. * **Open components:** Following shadcn/ui philosophy, every components used in `` are based on headless primitives available to you. * **Code first:** A single source of truth within your codebase to defined your agents and support behavior * **Beautiful Default:** The default `` comes with a carefully crafted support experience, powerful and beautiful as is * **AI-Ready:** Open code and code first for LLMs to read, understand, and improve. # Contacts URL: /docs/concepts/contacts ## What are Contacts? **Contacts** are identified [visitors](/docs/concepts/visitors). When you identify an anonymous visitor with an `externalId` (your user ID) or `email`, they become a contact. Contacts enable: * **Cross-device support**: Same user on desktop and mobile shares conversation history * **Rich metadata**: Attach context like plan type, MRR, company, or lifecycle stage * **Dashboard visibility**: Support agents see user details alongside conversations * **Persistent identity**: Conversations follow the user, not the device ## Creating Contacts ### Identification Requirements A contact requires **at least one** of: * `externalId`: Your internal user ID (recommended) * `email`: User's email address Both are accepted, but `externalId` is preferred for robust cross-system tracking. ### Using the Component ```tsx showLineNumbers title="app/dashboard/layout.tsx" import { IdentifySupportVisitor } from "@cossistant/next"; import { auth } from "@/lib/auth"; import { headers } from "next/headers"; export default async function DashboardLayout({ children }) { const session = await auth.api.getSession({ headers: await headers(), }); return (
{session?.user && ( )} {children}
); } ``` ### Using the Hook ```tsx showLineNumbers title="components/auth-handler.tsx" "use client"; import { useVisitor } from "@cossistant/next"; import { useEffect } from "react"; export function AuthHandler({ user }) { const { visitor, identify } = useVisitor(); useEffect(() => { if (user && !visitor?.contact) { identify({ externalId: user.id, email: user.email, name: user.name, image: user.avatar, metadata: { plan: user.plan, signupDate: user.createdAt, }, }); } }, [user, visitor?.contact, identify]); return null; } ``` ## Contact Metadata Metadata provides context to support agents during conversations. It appears in your dashboard alongside chat threads. ### What to Include Common metadata fields: * **plan**: Subscription tier (free, pro, enterprise) * **signupDate**: When the user joined * **company**: Organization name * **mrr**: Monthly recurring revenue * **lifecycleStage**: lead, trial, customer, churned * **lastActive**: Last activity timestamp ### Metadata Schema ```typescript type VisitorMetadata = Record; ``` Only primitive values are supported—no nested objects or arrays. ### Updating Metadata Metadata can be updated anytime to reflect user changes: ```tsx showLineNumbers title="components/upgrade-button.tsx" "use client"; import { useVisitor } from "@cossistant/next"; export function UpgradeButton() { const { setVisitorMetadata } = useVisitor(); const handleUpgrade = async () => { await upgradeToPro(); // Update metadata so agents see the new plan await setVisitorMetadata({ plan: "pro", upgradedAt: new Date().toISOString(), mrr: 99, }); }; return ; } ``` ## Efficient Metadata Updates Cossistant **hashes metadata** before sending updates. If metadata hasn't changed, no API call is made—preventing unnecessary network requests and database writes. This means you can safely call `setVisitorMetadata()` or re-render `` without performance concerns. ## One Contact, Multiple Visitors A single contact can have multiple [visitors](/docs/concepts/visitors) associated with it: * **Desktop visitor**: User on their laptop * **Mobile visitor**: Same user on their phone * **Tablet visitor**: Same user on their iPad All three visitors share: * Conversation history * Contact metadata * Support context This provides seamless support across devices—agents see the full picture regardless of where the user reaches out. ## Learn More * **[Visitors](/docs/concepts/visitors)**: Anonymous users before identification * **[IdentifySupportVisitor](/docs/support-component#identifying-visitors)**: Component for creating contacts * **[useVisitor](/docs/support-component/hooks#usevisitor)**: Hook for programmatic contact management * **[Conversations](/docs/concepts/conversations)**: Chat threads associated with contacts # Conversations URL: /docs/concepts/conversations ## What are Conversations? **Conversations** are threaded chat sessions between [visitors](/docs/concepts/visitors) (or [contacts](/docs/concepts/contacts)) and your support team. Each conversation has a timeline of [items](/docs/concepts/timeline-items)—messages, events, and more. ## Key Properties Every conversation includes: * **status**: `open` or `resolved` * **priority**: `low`, `medium`, `high`, or `urgent` * **participants**: Support agents (human or AI) involved * **tags**: Labels for categorization (billing, technical, onboarding, etc.) * **timeline**: Ordered list of [timeline items](/docs/concepts/timeline-items) * **lastTimelineItem**: Most recent activity for sorting/preview ## Conversation Lifecycle ### Creation Conversations are created when: * A visitor sends their first message through the support widget * A support agent initiates a conversation from the dashboard * Your backend creates one via the API ### Status Flow ``` open → resolved ↓ ↑ └───────┘ (can be reopened) ``` * **open**: Active conversation requiring attention * **resolved**: Conversation marked as complete (can be reopened) ### Priority Levels Conversations can be prioritized: * **low**: General questions, non-urgent feedback * **medium**: Standard support requests (default) * **high**: Important issues affecting user experience * **urgent**: Critical problems requiring immediate attention Support agents can adjust priority based on conversation context. ## Real-time Updates Conversations support **real-time synchronization** via WebSocket: * New messages appear instantly * Typing indicators show when agents are composing * Seen receipts track when messages are read * Status changes broadcast immediately The Cossistant SDK handles all WebSocket management automatically—no configuration needed. ## Conversation Timeline Each conversation has a timeline of [items](/docs/concepts/timeline-items): * **Messages**: Text and files from visitors or agents * **Events**: System activities (assigned, resolved, participant joined) * **Future items**: AI tool calls, interactive UI, custom actions The timeline provides a complete audit trail of the conversation. ### Example Timeline ``` 1. [MESSAGE] Visitor: "How do I reset my password?" 2. [EVENT] Agent Sarah joined the conversation 3. [MESSAGE] Sarah: "I can help! Click your profile..." 4. [EVENT] Conversation marked as resolved 5. [MESSAGE] Visitor: "Thanks, that worked!" 6. [EVENT] Conversation reopened ``` ## Multi-Agent Support Conversations can involve multiple participants: * **Human agents**: Support team members * **AI agents**: Automated assistants * **Mixed mode**: AI handles initial triage, escalates to humans Agents can: * Join and leave conversations * See full conversation history * Add internal notes (private [timeline items](/docs/concepts/timeline-items)) ## Tags and Organization Tag conversations for filtering and reporting: ```typescript tags: ["billing", "urgent", "enterprise-customer"]; ``` Tags help: * Route conversations to specialized teams * Generate reports and analytics * Filter dashboard views * Track common issue types ## Seen Tracking Cossistant tracks when participants last viewed a conversation: * **Visitors**: Automatic seen updates when widget is open * **Agents**: Tracked in dashboard * **Unread count**: Calculated per participant This powers unread badges in the support widget and dashboard. ## Cross-Device Continuity For identified [contacts](/docs/concepts/contacts), conversations sync across devices: * Start conversation on desktop * Continue on mobile * Same history, same context Anonymous [visitors](/docs/concepts/visitors) have device-specific conversations. ## Learn More * **[Timeline Items](/docs/concepts/timeline-items)**: Building blocks of conversations * **[Visitors](/docs/concepts/visitors)**: Anonymous users who start conversations * **[Contacts](/docs/concepts/contacts)**: Identified users with cross-device history # Visitors URL: /docs/concepts ## What are Visitors? **Visitors** are automatically created when someone loads your application with the Cossistant SDK. They represent anonymous users before they're identified as [contacts](/docs/concepts/contacts). Every visitor is unique per device/browser, persisting across page loads and sessions. ## How Visitors are Tracked Cossistant uses a combination of techniques to maintain visitor identity: * **LocalStorage**: Stores a unique visitor ID in the browser * **Fingerprinting**: Browser and device characteristics for additional persistence * **Automatic creation**: No setup required—visitors are created on first load This means a visitor on desktop and the same person on mobile will be two different visitors until they're [identified](/docs/concepts/contacts). ## Anonymous by Default Visitors start anonymous with no personal information: * No name, email, or external ID * Only browser-derived data (language, timezone) * Can start [conversations](/docs/concepts/conversations) without authentication * Perfect for public-facing pages or logged-out users ## Visitor Properties Each visitor has: * **id**: Unique identifier for this visitor * **language**: Browser language (e.g., "en-US") * **timezone**: Browser timezone (e.g., "America/New\_York") * **isBlocked**: Whether this visitor has been blocked from support * **contact**: The associated contact (null until identified) ## Identifying Visitors Transform anonymous visitors into identified [contacts](/docs/concepts/contacts) when users authenticate: ### Using the Component (Server Components) ```tsx showLineNumbers title="app/dashboard/layout.tsx" import { IdentifySupportVisitor } from "@cossistant/next"; import { auth } from "@/lib/auth"; import { headers } from "next/headers"; export default async function DashboardLayout({ children }) { const session = await auth.api.getSession({ headers: await headers(), }); return (
{session?.user && ( )} {children}
); } ``` ### Using the Hook (Client Components) ```tsx showLineNumbers title="components/auth-handler.tsx" "use client"; import { useVisitor } from "@cossistant/next"; import { useEffect } from "react"; export function AuthHandler({ user }) { const { visitor, identify } = useVisitor(); useEffect(() => { if (user && !visitor?.contact) { identify({ externalId: user.id, email: user.email, name: user.name, }); } }, [user, visitor?.contact, identify]); return null; } ``` Once identified, all conversations and data are linked to the [contact](/docs/concepts/contacts), even across different devices. ## Learn More * **[Contacts](/docs/concepts/contacts)**: Identified visitors with metadata and cross-device support * **[IdentifySupportVisitor](/docs/support-component#identifying-visitors)**: Component for visitor identification * **[useVisitor](/docs/support-component/hooks#usevisitor)**: Hook for programmatic visitor control # Timeline Items URL: /docs/concepts/timeline-items ## What are Timeline Items? **Timeline items** are the building blocks of [conversations](/docs/concepts/conversations). Instead of only supporting messages, Cossistant uses a flexible timeline architecture that supports multiple item types. This design enables rich, auditable conversation histories with: * **Messages**: Text and media from visitors or agents * **Events**: System activities and state changes * **Future expansion**: AI tool calls, interactive UI, custom actions ## Why Timeline Items? Traditional chat systems only handle messages. Cossistant's timeline architecture provides: * **Complete audit trail**: See when agents joined, when status changed, who resolved the conversation * **Rich context**: System events provide context between messages * **Extensibility**: New item types can be added without breaking existing conversations * **Flexibility**: Mix messages, events, and future interactive elements in one timeline ## Current Item Types ### Message Items Text and media content from visitors, agents, or AI. **Structure:** ```typescript { type: "message", parts: [ { type: "text", text: "How do I reset my password?" }, { type: "image", url: "...", mediaType: "image/png" } ], visitorId: "vis_123", // If from visitor userId: null, // If from human agent aiAgentId: null, // If from AI agent visibility: "public", // or "private" for internal notes createdAt: "2024-01-15T10:30:00Z" } ``` **Message Parts:** * **text**: Plain text content * **image**: Image attachments with URL and metadata * **file**: File attachments with URL, name, size Messages can have multiple parts (e.g., text + image). ### Event Items System-generated activities tracking conversation state changes. **Event Types:** * **assigned**: Agent assigned to conversation * **unassigned**: Agent removed from conversation * **participant\_joined**: Agent joined the conversation * **participant\_left**: Agent left the conversation * **status\_changed**: Conversation status updated (open ↔ resolved) * **priority\_changed**: Priority level adjusted * **tag\_added**: Tag applied to conversation * **tag\_removed**: Tag removed from conversation * **resolved**: Conversation marked as resolved * **reopened**: Resolved conversation reopened * **visitor\_blocked**: Visitor blocked from support * **visitor\_unblocked**: Visitor unblocked **Structure:** ```typescript { type: "event", parts: [ { type: "event", eventType: "participant_joined", actorUserId: "user_456", targetUserId: null, message: "Sarah joined the conversation" } ], visibility: "public", createdAt: "2024-01-15T10:32:00Z" } ``` Events capture **who** did **what** and **when**, creating a transparent history. ## Future Item Types The timeline architecture is designed to support upcoming features: ### AI Tool Calls ```typescript { type: "ai_tool_call", parts: [ { type: "tool_call", tool: "lookup_order", arguments: { orderId: "ord_789" }, result: { status: "shipped", tracking: "1Z..." } } ] } ``` ### Interactive UI ```typescript { type: "ui_element", parts: [ { type: "action_buttons", options: ["Resolve", "Escalate", "Request More Info"] } ] } ``` ### Custom Actions ```typescript { type: "custom_action", parts: [ { type: "refund_processed", amount: 99, orderId: "ord_789" } ] } ``` ## Timeline Item Properties All timeline items share common fields: * **id**: Unique identifier * **type**: Item type (message, event, etc.) * **parts**: Array of content parts * **conversationId**: Parent conversation * **visibility**: `public` or `private` (internal agent notes) * **createdAt**: Timestamp * **updatedAt**: Last modification timestamp **Actor fields** (who created the item): * **visitorId**: If created by visitor * **userId**: If created by human agent * **aiAgentId**: If created by AI agent ## Visibility Control Timeline items can be: * **public**: Visible to visitors and agents (default) * **private**: Internal agent notes, hidden from visitors This enables agents to: * Add context for other team members * Document resolutions internally * Share insights without visitor visibility ## Timeline Ordering Items are ordered chronologically by `createdAt` timestamp, providing a linear conversation history. The most recent item (`lastTimelineItem`) is cached on the conversation for: * Sorting conversations by activity * Displaying conversation previews * Determining unread status ## Learn More * **[Conversations](/docs/concepts/conversations)**: Chat threads containing timeline items * **[Visitors](/docs/concepts/visitors)**: Anonymous users who create timeline items * **[Contacts](/docs/concepts/contacts)**: Identified users with persistent timelines # Contributors Guide URL: /docs/others/contributors Welcome to Cossistant! This guide will help you get the project running locally and understand how to contribute effectively. ## Prerequisites Before you begin, make sure you have the following installed: * **Docker Desktop** - Required for running Postgres and Redis locally * **Bun v1.2+** - Our package manager and runtime ([install Bun](https://bun.sh)) * **Git** - For version control ## Quick Start Get up and running in three commands: ```bash git clone https://github.com/cossistantcom/cossistant.git cd cossistant bun install --workspaces bun dev ``` That's it! The `bun dev` command will: 1. Start Docker Compose (Postgres + Redis containers) 2. Start the API server with Upstash Workflow in local mode 3. Start the Next.js web application **Upstash Workflow runs locally** - No account needed! When the server starts, you'll see the workflow credentials displayed in your console. These credentials don't change between restarts. ## What's Running After `bun dev` completes, you'll have: * **API Server**: `http://localhost:3001` (Hono + tRPC + WebSocket) * **Web App**: `http://localhost:3000` (Next.js dashboard, docs, landing) * **Postgres**: `localhost:5432` (via Docker) * **Redis**: `localhost:6379` (via Docker) * **Upstash Workflow**: Local mode (credentials in console) ## Database Setup ### Default Connection The local database connection string is: ``` postgresql://postgres:postgres@localhost:5432/cossistant ``` This is automatically configured when you run `bun dev`. ### Running Migrations After starting the services for the first time, run the database migrations: ```bash cd apps/api bun db:migrate ``` ### Seeding Data (Optional) To populate the database with sample data for development: ```bash cd apps/api bun db:seed ``` ### Making Schema Changes When you need to modify the database schema: 1. Update the schema files in `apps/api/src/db/schema` 2. Generate a migration: ```bash cd apps/api bun db:generate ``` 3. Apply the migration: ```bash bun db:migrate ``` ### Database Studio To explore the database with Drizzle Studio: ```bash cd apps/api bun db:studio ``` ## Optional: S3 Setup S3 file storage is **only needed if you're testing file uploads**. For most development work, you can skip this. If you do need S3: 1. Navigate to the infrastructure directory: ```bash cd infra/aws/s3-public-setup ``` 2. Follow the instructions in the [S3 Setup README](/infra/aws/s3-public-setup/README.md) 3. The Terraform configuration will create the necessary AWS resources ## Project Structure Understanding the monorepo layout: ### Apps * **`apps/api`** - Hono + tRPC backend with WebSocket server * RESTful and tRPC APIs * Real-time WebSocket communication * Database queries and mutations * Authentication via Better Auth * Background jobs via Upstash Workflow * **`apps/web`** - Next.js application * Marketing landing page * Documentation (Fumadocs) * Dashboard interface ### Packages * **`packages/react`** - Main React SDK * Headless hooks and primitives * Pre-built `` component * Real-time WebSocket integration * **`packages/next`** - Next.js-specific SDK * Server Component support * Next.js optimized bindings * **`packages/core`** - Shared client logic * State management stores * REST and WebSocket clients * Utility functions * **`packages/types`** - TypeScript definitions * Shared types across all packages * API schemas and validation * **`packages/transactional`** - Email templates * React Email templates * Transactional email utilities * **`packages/location`** - Location utilities * Country and timezone data * Geolocation helpers ## Tech Stack Details ### Core Technologies * **Monorepo**: Turborepo for efficient builds and caching * **Runtime**: Bun for fast package management and execution * **Backend**: Hono (lightweight, fast API framework) * **Frontend**: React 19 + Next.js 15 * **Type Safety**: TypeScript throughout * **Database**: PostgreSQL via Drizzle ORM * **Authentication**: Better Auth * **Real-time**: WebSockets for live updates * **Background Jobs**: Upstash Workflow (runs locally in dev) * **Styling**: TailwindCSS v4 ### Development Tools * **Linting**: Biome (via Ultracite) * **Testing**: Bun's built-in test runner * **Documentation**: Fumadocs (Markdown-based) ## Development Workflow ### Common Commands Run these from the project root: ```bash # Start all services bun dev # Build all packages bun run build # Build specific package bun run build --filter @cossistant/react # Run linter and auto-fix issues bun run fix # Type check all packages bun run check-types # Check documentation links bun run docs:links ``` ### API-Specific Commands Run these from `apps/api`: ```bash # Start API server only bun run dev # Run migrations bun run db:migrate # Seed database bun run db:seed # Open Drizzle Studio bun run db:studio # Generate Better Auth schema bun run better-auth:generate-schema ``` ### Before Committing Always run these commands before committing: ```bash # Auto-fix linting issues bun run fix # Verify TypeScript types bun run check-types # Run tests (in relevant package) cd packages/react bun test ``` ### Testing Cossistant uses Bun's built-in test runner. Tests are colocated with source files using the `*.test.ts` naming convention. ```bash # Run tests in a specific package cd packages/react bun test # Watch mode bun test --watch # Coverage report bun test --coverage ``` ## Project Philosophy Cossistant is built with these core principles: ### Code-First, Not Clicks We prefer programmatic solutions over UI configuration. Our documentation includes code examples you can copy and paste, not screenshots of admin panels. ### API-First Design Every feature is accessible via API before it gets a UI. This ensures flexibility and enables headless usage patterns. ### Headless Components Our React components are unstyled and composable, giving you complete control over the look and feel while we handle the complex state management and real-time synchronization. ### TypeScript-First Type safety isn't optional—it's built in from the ground up. This catches errors early and provides excellent IntelliSense in your editor. ### Developer Experience is Paramount We optimize for developer happiness: * Clear error messages * Comprehensive documentation * Fast build times * Minimal configuration * AI-friendly docs that are easy to search and reference ### Open & Transparent Everything is in the open. Our development happens on GitHub, our roadmap is public, and we welcome contributions from the community. ## Contributing Guidelines ### Conventional Commits We follow [Conventional Commits](https://www.conventionalcommits.org/) for commit messages: * `feat:` - New features * `fix:` - Bug fixes * `docs:` - Documentation changes * `chore:` - Maintenance tasks * `refactor:` - Code refactoring * `test:` - Test updates Example: `feat: add message reactions to timeline items` ### Pull Requests When submitting a PR: 1. Create a descriptive title following Conventional Commits 2. Link related issues 3. Describe what changed and why 4. Note any environment or configuration changes 5. Include screenshots for UI changes 6. Ensure all tests pass locally ### Changesets For changes to published packages (`@cossistant/react`, `@cossistant/next`), add a changeset: ```bash bun run changeset ``` Follow the prompts to describe your changes. This will be used to generate changelogs and version bumps. ## Getting Help * **Documentation**: [cossistant.com/docs](https://cossistant.com/docs) * **Discord**: [Join our community](https://discord.gg/vQkPjgvzcc) * **GitHub Issues**: [Report bugs or request features](https://github.com/cossistantcom/cossistant/issues) ## License Cossistant is licensed under **AGPL-3.0** for non-commercial use. For commercial use, please contact us at [anthony@cossistant.com](mailto:anthony@cossistant.com). Thank you for contributing to Cossistant! 🎉 # Mentions URL: /docs/others/mentions ## About Cossistant is a project by [Anthony Riera](https://x.com/_anthonyriera). ## Credits * [ui.shadcn.com](https://ui.shadcn.com) - For the inspiration, docs, code and components. * [Vercel](https://vercel.com) - Where we host all our projects and for maintaining NextJS & Turborepo. * [Railway](https://railway.com?referralCode=nOTIh8) - Where we host the hono backend. * [Midday](https://midday.ai) - For the initial inspiration, motivation to go open source and code structure. * [Anron Icons](https://anron.pro) - For the icons (we paid for the license ofc). ## License © 2025 [Cossistant](https://cossistant.com). open source under GPL-3.0 license. # Third-Party Services URL: /docs/others/third-party-services ## Overview Cossistant leverages best-in-class third-party services to deliver a secure, reliable, and performant customer support platform. We are committed to achieving SOC 2 Type II certification as soon as possible and have carefully selected service providers that maintain the highest security and compliance standards. ## Infrastructure & Hosting * **[Vercel](https://vercel.com)** - Hosts our Next.js web application and provides edge infrastructure for optimal performance worldwide. * **[Railway](https://railway.com)** - Hosts our Hono backend API, Redis instance, and provides automatic deployments with monitoring. * **[AWS S3](https://aws.amazon.com/s3/)** - Secure cloud storage for file uploads and media assets (SOC 2 Type II certified). * **[AWS CloudFront](https://aws.amazon.com/cloudfront/)** - Content delivery network (CDN) for fast, global content distribution (SOC 2 Type II certified). * **[Upstash](https://upstash.com)** - QStash and Workflows for serverless background job processing and workflow orchestration (SOC 2 Type II certified). ## Database & Storage * **[PostgreSQL](https://www.postgresql.org/)** - Primary database for all application data. * **[Drizzle ORM](https://orm.drizzle.team/)** - Type-safe database toolkit and ORM. ## Authentication & Payments * **[Better Auth](https://www.better-auth.com/)** - Modern authentication solution for secure user authentication. * **[Polar.sh](https://polar.sh)** - Payment processing and subscription management for our billing system. ## Communication * **[Resend](https://resend.com)** - Transactional email delivery with high deliverability rates (SOC 2 Type II certified). ## Monitoring & Analytics * **[Vercel Analytics](https://vercel.com/analytics)** - Privacy-friendly web analytics and performance monitoring. * **[OpenStatus](https://www.openstatus.dev/)** - Uptime monitoring and status page infrastructure. ## Security & Compliance Commitment All third-party services we use are carefully vetted for: * SOC 2 Type II compliance (current or in progress) * GDPR compliance * Robust data encryption (in transit and at rest) * Regular security audits and penetration testing * High availability and disaster recovery capabilities We regularly review our vendor landscape to ensure we maintain the highest standards of security and privacy for our customers. # Customization URL: /docs/support-component/customization ## Overview Every part of the Support widget can be customized while keeping the **zero-config** experience intact. Style with **Tailwind classes** or replace entire components with **slots**. ## Custom Styling with classNames Override styles for specific parts of the widget: ```tsx ``` ### Available classNames * **`root`** - The outermost container (positioning, spacing) * **`bubble`** - The floating chat button * **`container`** - The main widget dialog ## Custom Bubble Replace the default chat bubble with your own component using **slots**: ```tsx import { Support, type BubbleSlotProps } from "@cossistant/react"; import * as Primitive from "@cossistant/react/primitives"; const CustomBubble = ({ className }: BubbleSlotProps) => ( {({ isOpen, isTyping, unreadCount }) => (
{isOpen ? "✕" : isTyping ? "..." : "💬"} {unreadCount > 0 && {unreadCount}}
)}
); ``` ### Bubble Render Props The `Primitive.Bubble` component provides: | Prop | Type | Description | | ------------- | ------------ | ------------------------------------- | | `isOpen` | `boolean` | Whether the widget is currently open | | `unreadCount` | `number` | Number of unread messages | | `isTyping` | `boolean` | Whether an agent is typing | | `toggle` | `() => void` | Function to toggle widget open/closed | ## Custom Container Replace the widget container to control layout and animations: ```tsx import { Support, type ContainerSlotProps } from "@cossistant/react"; const CustomContainer = ({ className, children, position, align }: ContainerSlotProps) => (
{children}
); ``` ## Custom Router For complete control over routing logic: ```tsx import { Support, type RouterSlotProps, useSupportNavigation } from "@cossistant/react"; import * as Primitive from "@cossistant/react/primitives"; const CustomRouter = ({ children }: RouterSlotProps) => { const { current } = useSupportNavigation(); return ( <> {children} ); }; ``` ## Slot Types Reference All slot components receive typed props: ```tsx type BubbleSlotProps = { className?: string; }; type ContainerSlotProps = { className?: string; children: React.ReactNode; position?: "top" | "bottom"; align?: "right" | "left"; }; type RouterSlotProps = { children?: React.ReactNode; }; ``` ## Full Example Combine multiple customizations: ```tsx import { Support } from "@cossistant/react"; import * as Primitive from "@cossistant/react/primitives"; const MyBubble = ({ className }) => ( {({ isOpen }) => {isOpen ? "×" : "?"}} ); export default function App() { return ( ); } ``` # Hooks URL: /docs/support-component/hooks ## Overview Cossistant provides React hooks for programmatic control over the support widget and visitor identification. These hooks are ideal when you need to integrate support functionality into custom components or respond to application events. ## useSupport Access support widget state and controls from any client component. ### Basic Example ```tsx showLineNumbers title="components/custom-support-button.tsx" "use client"; import { useSupport } from "@cossistant/next"; export function CustomSupportButton() { const { isOpen, toggle, unreadCount } = useSupport(); return ( ); } ``` ### Return Values void", required: true, returns: "void", }, close: { description: "Function to close the support widget", type: "() => void", required: true, returns: "void", }, toggle: { description: "Function to toggle the widget open/closed state", type: "() => void", required: true, returns: "void", }, unreadCount: { description: "Number of unread messages across all conversations", type: "number", required: true, }, availableHumanAgents: { description: "List of human support agents currently available", type: "HumanAgent[]", typeDescriptionLink: "#humanagent", required: true, }, availableAIAgents: { description: "List of AI agents configured for support", type: "AIAgent[]", typeDescriptionLink: "#aiagent", required: true, }, client: { description: "CossistantClient instance for direct API access", type: "CossistantClient", typeDescriptionLink: "#cossistantclient", required: true, }, isLoading: { description: "Whether website data is still loading", type: "boolean", required: true, }, error: { description: "Error object if website data failed to load", type: "Error | null", required: true, }, size: { description: "Widget size configuration", type: '"normal" | "larger"', required: true, }, }} /> ## useVisitor Programmatically identify visitors and manage contact metadata. Important: Metadata storage Metadata is stored on **contacts**, not visitors. You must call `identify()` before `setVisitorMetadata()` will work. Learn more about{" "} visitors and{" "} contacts. ### Example: Identify on Auth ```tsx showLineNumbers title="components/auth-handler.tsx" "use client"; import { useVisitor } from "@cossistant/next"; import { useEffect } from "react"; export function AuthHandler({ user }) { const { visitor, identify } = useVisitor(); useEffect(() => { // Only identify if we have a user and visitor isn't already a contact if (user && !visitor?.contact) { identify({ externalId: user.id, email: user.email, name: user.name, image: user.avatar, }); } }, [user, visitor?.contact, identify]); return null; } ``` ### Example: Update Metadata on Action ```tsx showLineNumbers title="components/upgrade-button.tsx" "use client"; import { useVisitor } from "@cossistant/next"; export function UpgradeButton() { const { setVisitorMetadata } = useVisitor(); const handleUpgrade = async () => { // Upgrade user's plan await upgradeToPro(); // Update contact metadata so support agents see the change await setVisitorMetadata({ plan: "pro", upgradedAt: new Date().toISOString(), mrr: 99, }); }; return ; } ``` ### Return Values Promise<...>", typeDescription: "(params: IdentifyParams) => Promise<{ contactId: string; visitorId: string } | null>", required: true, parameters: [ { name: "params", description: "Identification parameters including externalId, email, name, image, and metadata. See IdentifyParams type below.", }, ], returns: "Promise<{ contactId: string; visitorId: string } | null> - Returns the contact and visitor IDs on success, or null on failure", }, setVisitorMetadata: { description: "Update metadata for the identified contact", type: "(metadata: VisitorMetadata) => Promise<...>", typeDescription: "(metadata: VisitorMetadata) => Promise", required: true, parameters: [ { name: "metadata", description: "Metadata object to merge into the contact's existing metadata. See VisitorMetadata type below.", }, ], returns: "Promise - Returns the updated visitor object on success, or null on failure", }, }} /> ### identify() Parameters ", typeDescriptionLink: "#visitormetadata", required: false, }, }} /> Prefer declarative code? Use the{" "} IdentifySupportVisitor {" "} component for a simpler, declarative approach to visitor identification in Server Components. ## Types ### PublicVisitor The visitor object returned by the widget, representing an anonymous or identified visitor. ### PublicContact Contact information for an identified visitor. ### PublicWebsiteResponse Website configuration and agent availability information. ### HumanAgent Information about a human support agent. ### AIAgent Information about an AI support agent. ### CossistantClient The underlying client instance for direct API access. Used for advanced programmatic control. ### IdentifyParams Parameters for the identify() function. ", typeDescriptionLink: "#visitormetadata", required: false, }, }} /> ### VisitorMetadata Key-value pairs for storing custom data about contacts. **Type Definition:** `Record` ### SenderType Enum defining who can send messages. **Type Definition:** `"visitor" | "team_member" | "ai"` # Basic usage URL: /docs/support-component ## Philosophy The `` component is built on the principle of **simplicity first**. Drop it into your React app and get a fully functional support system without configuration overhead. ## How it Works * **Zero Config**: Works out of the box with sensible defaults * **Progressive Enhancement**: Start simple, customize as needed * **Real-time Chat**: Built-in WebSocket support for live conversations * **Smart Routing**: Automatically routes conversations to appropriate channels * **Headless Architecture**: Full control through primitive components when needed The component handles the complexity of modern support systems while maintaining a clean, minimal API surface. ## Customizing Messages & Quick Options Use the `` component to customize default messages and quick options per page or route. This is perfect for providing context-specific help. ### Example: Pricing Page ```tsx showLineNumbers title="app/pricing/page.tsx" import { SupportConfig } from "@cossistant/next"; export default function PricingPage() { return ( <>

Choose your plan

{/* rest of pricing page */} ); } ``` The `` component accepts the following props: ## Identifying Visitors By default, visitors are **anonymous**. Use `` to connect them to your authenticated users, transforming them into [contacts](/docs/concepts/contacts). Once identified, all conversations and metadata are linked to the contact across devices. ### Example: Dashboard Layout with Better Auth ```tsx showLineNumbers title="app/dashboard/layout.tsx" import { IdentifySupportVisitor } from "@cossistant/next"; import { auth } from "@/lib/auth"; import { headers } from "next/headers"; export default async function DashboardLayout({ children, }: { children: React.ReactNode; }) { const session = await auth.api.getSession({ headers: await headers(), }); return (
{session?.user && ( )} {children}
); } ``` What happens when I identify a visitor? The anonymous visitor becomes associated with a contact. All their conversations, metadata, and future interactions are linked to this contact—even across different devices. Learn more about{" "} visitors and{" "} contacts. ### Props ", typeDescriptionLink: "#visitormetadata", required: false, }, }} /> Need programmatic control? Use the{" "} useVisitor hook to identify visitors or update metadata from client components. ## Support Component Props The `` component accepts these optional props to customize its appearance and behavior: , container?: ComponentType, router?: ComponentType }", required: false, }, classNames: { description: "Granular className overrides for specific parts of the widget", type: "object", typeDescription: "{ root?: string, bubble?: string, container?: string }", required: false, }, children: { description: "Declarative Page components to register custom routes", type: "React.ReactNode", required: false, }, quickOptions: { description: "Quick reply options for this specific widget instance", type: "string[]", required: false, }, defaultMessages: { description: "Welcome messages shown before conversation starts", type: "DefaultMessage[]", typeDescriptionLink: "#defaultmessage", required: false, }, defaultOpen: { description: "Whether the widget should open automatically on mount", type: "boolean", required: false, }, locale: { description: "Locale string for widget translations (e.g., 'en', 'fr', 'es')", type: "string", required: false, }, content: { description: "Custom text content overrides for widget copy", type: "Partial", typeDescription: "Partial record of all text strings used in the widget for internationalization and customization", required: false, }, }} /> ### Usage Examples Basic customization with theme and styling: ```tsx ``` With custom page: ```tsx import { Support, Page, useSupportNavigation } from "@cossistant/next"; const HelpPage = () => { const { goBack } = useSupportNavigation(); return (

Help Center

); }; export default function App() { return ( ); } ``` For advanced customization, see the [Custom Components](/docs/support-component/custom-components) guide. ## Types ### DefaultMessage Structure for pre-conversation welcome messages. ### VisitorMetadata Key-value pairs for storing custom data about contacts. **Type Definition:** `Record` ### SenderType Enum defining who can send messages. **Type Definition:** `"visitor" | "team_member" | "ai"` # Primitives URL: /docs/support-component/primitives ## Philosophy Primitives are **headless UI components** that give you complete control over styling and behavior. Inspired by **shadcn/ui**, they follow these principles: * **Unstyled by default** - Bring your own Tailwind classes * **Fully composable** - Build complex UIs from simple pieces * **Developer-owned** - Copy, modify, and extend as needed * **Accessible** - Built-in ARIA patterns and keyboard navigation Use primitives when you need **complete control** over the support experience. ## Quick Example ```tsx import * as Primitive from "@cossistant/react/primitives"; {({ isOpen, close }) => (
)}
{({ toggle }) => ( )}
``` ## Primitives Reference ### Layout & Structure **``** Context provider for declarative page registration. Wrap your app to enable `` and ``. ```tsx ``` **``** Generic router that renders registered pages. ```tsx ``` **``** Declaratively register a page component. ```tsx ``` **``** Dialog container with open/close state and escape key handling. ```tsx {({ isOpen, close }) => (
{isOpen &&

Dialog content

}
)}
``` **``** Floating action button with widget state. ```tsx {({ isOpen, unreadCount, isTyping, toggle }) => ( )} ``` ### Timeline & Messages **``** Message timeline with automatic scrolling and loading states. ```tsx {(item) => } ``` **``** Individual message or event in the timeline. ```tsx {message.text} {message.createdAt} ``` **``** Group consecutive messages by the same sender. ```tsx {user.name} {messages.map(msg => )} ``` ### Input & Interaction **``** Rich text input with file upload support. ```tsx ``` **``** File upload component with drag-and-drop. ```tsx ``` **` ``` ### Visual **``**, **``**, **``** User avatar with image and fallback. ```tsx {user.initials} ``` **``** Animated typing indicator. ```tsx ``` ### Configuration **``** Configure widget behavior per route or page. ```tsx ``` ## Building from Scratch Create a completely custom support experience: ```tsx import * as Primitive from "@cossistant/react/primitives"; import { useSupportStore } from "@cossistant/react"; export function CustomSupport() { const { isOpen, toggle } = useSupportStore(); const [page, setPage] = useState("HOME"); return ( {/* Custom bubble */} {({ toggle, unreadCount }) => ( )} {/* Custom window */} {({ close }) => (
)}
); } ``` ## Why Primitives? **Full control.** No opinionated styles or structure—build exactly what you need. **Type-safe.** All primitives are fully typed with TypeScript. **Framework-agnostic patterns.** Principles work in any React environment. Use the `` component for quick setup. Use primitives when you need **complete freedom**. # Routing & Pages URL: /docs/support-component/routing ## Overview Add custom pages to the Support widget using **declarative `` components**. All navigation is **strongly typed** with full autocomplete for route names and parameters. ## Adding a Custom Page ### Step 1: Define route types Type augmentation enables **full TypeScript autocomplete** for your custom routes: ```tsx declare module "@cossistant/core" { interface RouteRegistry { SETTINGS: { tab: string }; HELP: undefined; } } ``` ### Step 2: Create your page component ```tsx import { useSupportNavigation, Header, Button } from "@cossistant/react"; const SettingsPage = ({ params }) => { const { navigate, goBack, canGoBack } = useSupportNavigation(); return ( <>
{canGoBack && }

Settings

Current tab: {params?.tab}

); }; ``` ### Step 3: Register with `` ```tsx import { Support, Page } from "@cossistant/react"; ``` ### Step 4: Navigate ```tsx const { navigate } = useSupportNavigation(); // ✅ Fully typed with autocomplete navigate({ page: "SETTINGS", params: { tab: "profile" } }); ``` ## Navigation Hooks The `useSupportNavigation` hook provides everything needed for routing: ```tsx import { useSupportNavigation } from "@cossistant/react"; const MyPage = () => { const { navigate, // Navigate to a page (adds to history) replace, // Replace current page (no history) goBack, // Go to previous page canGoBack, // Can navigate back? current, // Current navigation state page, // Current page name params, // Current page params } = useSupportNavigation(); return (
{canGoBack && }

Page: {page}

); }; ``` ### Navigation Methods | Method | Description | Example | | ------------ | ---------------------------------- | ------------------------------------------------------------ | | `navigate()` | Go to a new page (adds to history) | `navigate({ page: "SETTINGS", params: { tab: "profile" } })` | | `replace()` | Replace current page (no history) | `replace({ page: "HOME" })` | | `goBack()` | Return to previous page | `goBack()` | ## Built-in Pages The widget includes four default pages: ```tsx // Home page navigate({ page: "HOME" }); // Articles/FAQ page navigate({ page: "ARTICLES" }); // Conversation page navigate({ page: "CONVERSATION", params: { conversationId: "abc123", initialMessage: "Hello!" } }); // Conversation history navigate({ page: "CONVERSATION_HISTORY" }); ``` ## Type Safety TypeScript validates **both route names and params**: ```tsx // ✅ Valid - conversationId is required navigate({ page: "CONVERSATION", params: { conversationId: "123" } }); // ❌ TypeScript error - missing required param navigate({ page: "CONVERSATION", params: {} }); // ✅ Custom routes work too navigate({ page: "SETTINGS", params: { tab: "profile" } }); // ❌ TypeScript error - invalid page name navigate({ page: "UNKNOWN_PAGE" }); ``` ## Building UI Components Use exported components to build custom pages: ```tsx import { Header, Button, Text, useSupportText, useSupportNavigation } from "@cossistant/react"; const HelpPage = () => { const { goBack } = useSupportNavigation(); const text = useSupportText(); return ( <>

Help Center

); }; ``` ## Complete Example ```tsx "use client"; import { Support, Page, useSupportNavigation } from "@cossistant/react"; // 1. Extend types declare module "@cossistant/core" { interface RouteRegistry { FAQ: undefined; SETTINGS: { section: string }; } } // 2. Create pages const FAQPage = () => { const { goBack } = useSupportNavigation(); return (

FAQ

); }; const SettingsPage = ({ params }) => { const { navigate } = useSupportNavigation(); return (

Settings - {params?.section}

); }; // 3. Register and use export default function App() { return ( ); } // 4. Navigate from anywhere function MyButton() { const { navigate } = useSupportNavigation(); return ( ); } ``` ## Tips **Keep it simple.** Start with ``, add custom pages only when needed. **Use type augmentation.** Always extend `RouteRegistry` for full type safety. **Leverage hooks.** Use `useSupportNavigation` for routing, `useSupportText` for i18n, `useSupport` for data. # Locale & Text URL: /docs/support-component/text ## Overview The support widget ships with a fully typed translation layer powered by the `` component and the `useSupportText()` hook. Every key is defined in a single source of truth so you get auto-complete, variable hints and compiler errors if a required placeholder is missing. * Built-in locales: **English (`en`)**, **French (`fr`)** and **Spanish (`es`)** * Fallback order: provided `locale` prop → browser locale → English defaults * Keys always render with a `data-key-name="…"` attribute so you can discover them quickly in dev tools ## Rendering copy Use the typed `` component for static markup or the hook when you need raw strings. ```tsx import { Text, useSupportText } from "@cossistant/react/support"; export const AskButton = () => { const text = useSupportText(); return ( ); }; ``` Both APIs are memo-friendly; the formatter is stable between renders and only re-computes when locale, overrides or context change. ## Providing locales & overrides Developers control the active locale and individual strings through the `Support` component. You can pass literal strings, per-locale overrides or formatter functions with full access to widget context (visitor, agents) plus utility helpers. ```tsx { const period = utils.timeOfDay(); const visitorName = variables?.visitorName ?? context.visitor?.contact?.name ?? ""; const prefix = period.token === "evening" ? "Bonsoir" : "Salut"; return `${prefix} ${visitorName}!`; }, "common.actions.askQuestion": { en: "Reach out", fr: "Contactez-nous", }, }} /> ``` Custom locales are supported too—just pass a new locale code and supply the strings under `content`. ## Debugging helpers Every rendered `` sets `data-key-name=""`, making it easy to inspect copy in the DOM. The translation utilities also expose helpers such as `formatNumber`, `pluralize`, `titleCase` and a `timeOfDay()` helper, available to formatter functions via the `utils` parameter. These guarantees keep the widget copy consistent, type-safe and ready for your team's voice. # Theme URL: /docs/support-component/theme ## Overview The Support widget is **fully isolated** from your app's styles by default. All widget styles use the `co-` prefix, so they won't clash with your existing CSS. ## How Theming Works The widget checks two places for every style value: 1. **Your override** (`--co-theme-*` variables) 2. **Built-in default** (sensible OKLCH colors) ```css /* Widget looks for --co-theme-primary first */ --co-primary: var(--co-theme-primary, oklch(20.5% 0 0)); ``` ## Quick Start Override widget colors by setting `--co-theme-*` variables: ```css .cossistant { --co-theme-primary: #3b82f6; --co-theme-background: #ffffff; --co-theme-foreground: #0f172a; --co-theme-radius: 12px; } ``` ## Available Theme Variables | Variable | Default (Light) | Default (Dark) | | ------------------------------- | ------------------ | ------------------ | | `--co-theme-background` | `oklch(99% 0 0)` | `oklch(15.5% 0 0)` | | `--co-theme-foreground` | `oklch(14.5% 0 0)` | `oklch(98.5% 0 0)` | | `--co-theme-primary` | `oklch(20.5% 0 0)` | `oklch(98.5% 0 0)` | | `--co-theme-primary-foreground` | `oklch(98.5% 0 0)` | `oklch(20.5% 0 0)` | | `--co-theme-border` | `oklch(92.2% 0 0)` | `oklch(26.9% 0 0)` | | `--co-theme-muted` | Color-mixed | Color-mixed | | `--co-theme-muted-foreground` | Color-mixed | Color-mixed | | `--co-theme-radius` | `0.625rem` | `0.625rem` |

Background

oklch(99% 0 0)

Foreground

oklch(14.5% 0 0)

Primary

oklch(20.5% 0 0)

Border

oklch(92.2% 0 0)
### Status Colors | Variable | Default | | ------------------------ | --------------------------- | | `--co-theme-destructive` | `oklch(57.7% 0.245 27.325)` | | `--co-theme-success` | `oklch(71.7% 0.18 142)` | | `--co-theme-warning` | `oklch(86.4% 0.144 99)` | | `--co-theme-neutral` | `oklch(60.8% 0 0)` |

Destructive

oklch(57.7% 0.245 27.325)

Success

oklch(71.7% 0.18 142)

Warning

oklch(86.4% 0.144 99)

Neutral

oklch(60.8% 0 0)
### Accent Colors | Variable | Default | | ------------------- | ------------------------ | | `--co-theme-pink` | `oklch(76.3% 0.152 354)` | | `--co-theme-yellow` | `oklch(86.4% 0.144 99)` | | `--co-theme-blue` | `oklch(72.5% 0.132 241)` | | `--co-theme-orange` | `oklch(74.5% 0.166 50)` |

Pink

oklch(76.3% 0.152 354)

Yellow

oklch(86.4% 0.144 99)

Blue

oklch(72.5% 0.132 241)

Orange

oklch(74.5% 0.166 50)
## Light and Dark Mode ### Using the theme prop Force a specific theme regardless of your app's settings: ```tsx // Force dark theme // Force light theme (default) ``` ### Automatic theme detection (default) By default, the widget automatically adapts to your app's theme. It looks for: 1. `.dark` class on any parent element 2. `data-color-scheme="dark"` attribute on any parent element This works seamlessly with popular theme libraries like **next-themes** and **shadcn's theme system**. ```tsx // Widget adapts automatically // Or with data attribute
``` ## Using shadcn/ui Colors Want the widget to match your shadcn/ui theme? Map shadcn variables to widget variables: ```css :root { --co-theme-background: var(--background); --co-theme-foreground: var(--foreground); --co-theme-primary: var(--primary); --co-theme-primary-foreground: var(--primary-foreground); --co-theme-border: var(--border); --co-theme-radius: var(--radius); } ``` This gives you full control—the widget only uses shadcn colors when you explicitly connect them. ## Custom Branding Match your brand identity with custom colors: ```css .cossistant { --co-theme-primary: #ff6b35; --co-theme-primary-foreground: #ffffff; --co-theme-background: #fafafa; --co-theme-foreground: #1a1a1a; --co-theme-border: #e5e5e5; --co-theme-radius: 16px; } ``` ## Advanced: Per-Shade Overrides Fine-tune background shades for depth and hierarchy: ```css .cossistant { --co-theme-background-50: #fafafa; --co-theme-background-100: #f5f5f5; --co-theme-background-200: #eeeeee; --co-theme-background-300: #e0e0e0; } ``` By default, these are generated with `color-mix()` from your base colors. # NextJS URL: /docs/quickstart ## Install the packages Let's start by adding Cossistant to your NextJS project: ```bash npm install @cossistant/next @cossistant/react ``` ## Add your public API key Add your public API key to the `NEXT_PUBLIC_COSSISTANT_API_KEY` environment variable. ```bash NEXT_PUBLIC_COSSISTANT_API_KEY=pk_test_xxxx ``` Where to find your public API key? You can find your public API key at the end of your onboarding or can access it anytime from the settings page. ## Add Cossistant provider Add the Cossistant `SupportProvider` to the root layout of your app: ```tsx {1,13} showLineNumbers title="app/layout.tsx" import { SupportProvider } from "@cossistant/next"; import "./globals.css"; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( {children} ); } ``` ## Import support widget styling Cossistant support widget provides two CSS options depending on your setup: Tailwind v4 Plain CSS If you're using Tailwind CSS v4, import the source file in your CSS to enable full theme customization: ```css {3} showLineNumbers title="app/globals.css" @import "tailwindcss"; @import "@cossistant/react/tailwind.css"; ``` This allows you to override variables like `--co-theme-primary` in your own CSS for theming. Tailwind v3 users Tailwind v3 is not supported. Please use the plain CSS import instead (see "Plain CSS" tab). Import the pre-compiled CSS in your layout - works with any setup, no Tailwind required: ```tsx {4} showLineNumbers title="app/layout.tsx" import { SupportProvider } from "@cossistant/next"; import "./globals.css"; import "@cossistant/next/support.css"; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( {children} ); } ``` ## Use support widget Add the Cossistant `` widget to your app: ```tsx {1,8} showLineNumbers title="app/page.tsx" import { Support } from "@cossistant/next"; export default function Page() { return (

You're ready to go!

{/* Support widget can be placed anywhere in your app */}
); } ```
## Done! You're ready to go! You can now start using Cossistant `` widget in your app. Simple isn't it? You can stop here or move on to the basic usage guide to learn how to use and customize your support widget, to make it truly yours.
``` ``` # React URL: /docs/quickstart/react ## Setup The full documentation for react and other frameworks will be available as soon as possible ❤️ # Create a contact URL: /docs/v1/contacts/post {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Creates a new contact for the website # List conversations for a visitor URL: /docs/v1/conversations/get {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Fetch paginated list of conversations for a specific visitor with optional filters. # Create a conversation (optionally with initial timeline items) URL: /docs/v1/conversations/post {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Create a conversation; optionally pass a conversationId and a set of default timeline items. # Send a message (timeline item) to a conversation URL: /docs/v1/messages/post {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Send a new message (timeline item) to an existing conversation. # Get website information URL: /docs/v1/websites/get {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Returns the website information associated with the provided API key. This endpoint supports both public and private API keys with different authentication methods. # Identify a visitor URL: /docs/v1/contacts/identify/post {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Creates or updates a contact for a visitor. If a contact with the same externalId or email exists, it will be updated. The visitor will be linked to the contact. # Delete a contact URL: /docs/v1/contacts/:id/delete {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Soft deletes a contact # Get a contact URL: /docs/v1/contacts/:id/get {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Retrieves a contact by ID # Update a contact URL: /docs/v1/contacts/:id/patch {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Updates an existing contact # Create a contact organization URL: /docs/v1/contacts/organizations/post {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Creates a new contact organization for the website # Get a single conversation by ID URL: /docs/v1/conversations/conversationid/get {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Fetch a specific conversation by its ID. # Retrieve an organization URL: /docs/v1/organizations/:id/get {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Retrieve an organization by its ID for the authenticated organization. # Generate a signed S3 upload URL URL: /docs/v1/uploads/sign-url/post {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Creates a temporary signed URL that can be used to upload a file directly to the configured S3 bucket. # Get visitor information URL: /docs/v1/visitors/:id/get {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Retrieves visitor information by visitor ID # Update existing visitor information URL: /docs/v1/visitors/:id/patch {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Updates an existing visitor's browser, device, and location data. The visitor must already exist in the system. # Update contact metadata URL: /docs/v1/contacts/:id/metadata/patch {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Merges the provided metadata into the contact profile # Delete a contact organization URL: /docs/v1/contacts/organizations/:id/delete {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Soft deletes a contact organization # Get a contact organization URL: /docs/v1/contacts/organizations/:id/get {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Retrieves a contact organization by ID # Update a contact organization URL: /docs/v1/contacts/organizations/:id/patch {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Updates an existing contact organization # Get conversation seen data URL: /docs/v1/conversations/conversationid/seen/get {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Fetch the seen data (read receipts) for a conversation, showing who has seen messages and when. # Mark a conversation as seen by the visitor URL: /docs/v1/conversations/conversationid/seen/post {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Record a visitor's last seen timestamp for a specific conversation. # Get conversation timeline items URL: /docs/v1/conversations/conversationid/timeline/get {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Fetch paginated timeline items (messages and events) for a conversation in chronological order. # Report a visitor typing state URL: /docs/v1/conversations/conversationid/typing/post {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Emit a typing indicator event for the visitor. Either visitorId must be provided via body or headers. # Update contact metadata for a visitor URL: /docs/v1/visitors/:id/metadata/patch {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} Merges the provided metadata into the contact profile associated with the visitor. The visitor must be identified first (linked to a contact) via the /contacts/identify endpoint.