Sharing Conversations
Share Atlas conversations via public or org-scoped links with configurable expiry.
Atlas lets you share conversations via links with configurable expiry and access controls. Public shares are visible to anyone with the link. Organization-scoped shares require authentication. Shared conversations include rich OpenGraph metadata for social previews.
Prerequisites
- Internal database (
DATABASE_URL) — conversation history and sharing are unavailable without it
Creating a Shared Link
From the UI
- Open a conversation in the Atlas chat interface.
- Click the Share button in the conversation header.
- Choose an expiry duration (1 hour, 24 hours, 7 days, 30 days, or never).
- Optionally toggle Organization only to restrict access to authenticated users.
- Click Create share link — Atlas generates a unique share link. Copy it to your clipboard.
The share dialog also provides an iframe embed snippet for embedding the conversation in other pages.
To revoke a shared link, open the share dialog again and click Remove share link. The public link will immediately stop working.
From the API
Create and revoke share links programmatically:
# Share a conversation (with expiry and share mode)
curl -X POST https://your-atlas-api.example.com/api/v1/conversations/{id}/share \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{"expiresIn": "7d", "shareMode": "public"}'
# Response:
# {
# "token": "abc123...",
# "url": "https://your-atlas-api.example.com/shared/abc123...",
# "expiresAt": "2026-03-19T00:00:00.000Z",
# "shareMode": "public"
# }Available expiresIn values: "1h", "24h", "7d", "30d", "never" (default: "never").
Available shareMode values: "public" (anyone with link), "org" (authenticated users only).
# Revoke sharing
curl -X DELETE https://your-atlas-api.example.com/api/v1/conversations/{id}/share \
-H "Authorization: Bearer your-api-key"From the SDK
import { createAtlasClient } from "@useatlas/sdk";
const atlas = createAtlasClient({
baseUrl: "https://your-atlas-api.example.com",
apiKey: "your-api-key",
});
// Generate a share link (options like expiresIn and shareMode are available via the REST API)
const { token, url } = await atlas.conversations.share("conversation-id");
// Revoke the share link — it stops working immediately
await atlas.conversations.unshare("conversation-id");Public View
Shared conversations are visible at /shared/{token}. The page displays:
- Header — Atlas branding, "Shared conversation" label, and creation date
- Conversation title — derived from the first user message
- Messages — user and assistant messages rendered in a clean, read-only format (system and tool messages are hidden)
No authentication is required to view a shared conversation. The public endpoint has its own rate limiter to prevent abuse. Assistant messages containing only non-text parts (such as tool call results) will appear empty in the shared view.
OpenGraph & Social Previews
Shared conversation pages include OpenGraph and Twitter Card metadata for rich social previews when links are shared on Slack, Twitter, LinkedIn, etc.
| Meta Tag | Value |
|---|---|
og:title | First user message (truncated to 60 characters), e.g. "Atlas: What were our top 10 customers by revenue?" |
og:description | First assistant response (truncated to 160 characters) |
og:type | article |
og:site_name | Atlas |
twitter:card | summary |
When the conversation has no user messages, the title falls back to the conversation title or "Atlas — Shared Conversation". When the assistant response is only tool calls (no text), the description uses a generic fallback.
Iframe Embedding
Embed a shared conversation in another page using the /embed variant:
<iframe
src="https://your-atlas-app.example.com/shared/{token}/embed"
title="Atlas Conversation"
style="width: 100%; height: 500px; border: 1px solid #e4e4e7; border-radius: 8px;"
></iframe>The embed view is a compact, chromeless version of the shared conversation — no header, smaller avatars, and a "Powered by Atlas" footer. It supports both light and dark modes (follows system preference).
This is ideal for embedding conversation transcripts in documentation, blog posts, or dashboards.
API Reference
Share
POST /api/v1/conversations/:id/shareGenerates a cryptographically random share token and returns the public URL. Requires authentication. If the conversation is already shared, a new token replaces the old one.
Request body (optional):
{
"expiresIn": "7d",
"shareMode": "public"
}| Field | Type | Default | Description |
|---|---|---|---|
expiresIn | "1h" | "24h" | "7d" | "30d" | "never" | "never" | When the link expires |
shareMode | "public" | "org" | "public" | public = anyone with link; org = authenticated users only |
Response:
{
"token": "abc123...",
"url": "https://your-atlas-api.example.com/shared/abc123...",
"expiresAt": "2026-03-19T00:00:00.000Z",
"shareMode": "public"
}Unshare
DELETE /api/v1/conversations/:id/shareRevokes the share token. The public link stops working immediately. Returns 204 No Content on success.
View Shared Conversation
GET /api/public/conversations/:tokenReturns the conversation with messages. Public shares require no authentication. Organization-scoped shares (shareMode: "org") require authentication — unauthenticated requests receive 403. Expired links return 410 Gone. Rate-limited per IP (60 requests per minute).
Response:
{
"title": "Revenue Analysis",
"surface": "web",
"createdAt": "2026-03-12T00:00:00Z",
"messages": [
{
"role": "user",
"content": "What was last month's revenue?",
"createdAt": "2026-03-12T00:00:01Z"
},
{
"role": "assistant",
"content": "Last month's revenue was $1.2M...",
"createdAt": "2026-03-12T00:00:02Z"
}
]
}Security
- Tokens are random — share tokens are 28-character base64url strings generated with
crypto.randomBytes(21). They cannot be guessed. - Expiry enforcement — expired links are checked on every access (not just at creation). Expired tokens return
410 Gone. A background cleanup task also removes expired tokens from the database hourly. - Organization-scoped sharing — links with
shareMode: "org"require the viewer to be authenticated. Unauthenticated requests receive403. - Revocation is instant — unsharing clears the token from the database. Cached responses (Next.js 60s revalidate) will expire shortly after.
- No write access — shared conversation views are completely read-only. Viewers cannot modify or interact with the conversation.
- Rate limited — the public endpoint has a per-IP rate limiter (60 requests per minute, separate from the authenticated rate limiter) to prevent scraping.
Troubleshooting
Share button doesn't appear
Cause: Conversation sharing requires an internal database (DATABASE_URL). Without it, conversation history and sharing are unavailable.
Fix: Set DATABASE_URL to a PostgreSQL connection string and restart the server. The share button appears in the conversation header once the internal database is connected.
Shared link returns 410 Gone
Cause: The share link has expired. Links have a configurable expiry (1 hour to 30 days, or never).
Fix: Create a new share link with a longer expiry. When sharing via the API, set expiresIn to "never" for permanent links, or "30d" for longer-lived ones.
Social preview shows generic title
Cause: The conversation has no user messages, or the first assistant response contains only tool calls (no text). OpenGraph metadata falls back to generic values in these cases.
Fix: Ensure the conversation has at least one user message before sharing. The OG title is derived from the first user message (truncated to 60 characters).
For more, see Troubleshooting.