Build Cearsi into your product
The Cearsi platform ships as a REST API, a drop-in web widget, an MCP endpoint, and outbound webhooks — so you can embed the same financial education assistant your team uses inside your own app, portal, or agent.
Available on the Max and Business plans. Create keys in Settings → API Keys.
Quickstart
- Upgrade to Max on the billing page.
- Create an API key in Settings. Copy it — it's only shown once.
- Call
POST https://cearsi.dev/api/public/v1/chatwith a Bearer token.
REST API
Base URL: https://cearsi.dev/api/public/v1
POST /chat
Send a message and receive a response from Cearsi.
Edit locally, then paste into your project. Requests run from your own environment — Cearsi never executes this code.
curl https://cearsi.dev/api/public/v1/chat \
-H "Authorization: Bearer csk_live_..." \
-H "Content-Type: application/json" \
-d '{"message":"Explain how staking rewards are taxed in the US"}'const res = await fetch("https://cearsi.dev/api/public/v1/chat", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CEARSI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
message: "Explain how staking rewards are taxed in the US",
}),
});
const { message } = await res.json();
console.log(message.content);import os, requests
r = requests.post(
"https://cearsi.dev/api/public/v1/chat",
headers={"Authorization": f"Bearer {os.environ['CEARSI_API_KEY']}"},
json={"message": "Summarize MiCA in one paragraph"},
)
print(r.json()["message"]["content"]){
"id": "chatcmpl_...",
"object": "chat.completion",
"message": { "role": "assistant", "content": "..." },
"usage": { "prompt_tokens": 128, "completion_tokens": 220 }
}Passing a full conversation
{
"messages": [
{ "role": "user", "content": "What is a Roth IRA?" },
{ "role": "assistant", "content": "A Roth IRA is ..." },
{ "role": "user", "content": "What's the 2026 contribution limit?" }
]
}JavaScript SDK
One-file ES module hosted on the Cearsi CDN — no npm install, no build step.
import { Cearsi } from "https://cearsi.dev/sdk/v1/cearsi.js";
const c = new Cearsi({ apiKey: "csk_live_..." });
const { message } = await c.chat("Explain how staking rewards are taxed in the US");
console.log(message.content);Source: /sdk/v1/cearsi.js
Mobile SDK (React Native / Expo)
Same REST API, plus local conversation state, device persistence and a subscribe() hook so a chat screen re-renders automatically. Drop the file into your app (or vendor it from the CDN) and pass an AsyncStorage-compatible store.
# copy the SDK into your app
curl -o src/lib/cearsi-mobile.js https://cearsi.dev/sdk/v1/cearsi-mobile.js
npx expo install @react-native-async-storage/async-storage// src/lib/cearsi.js
import AsyncStorage from "@react-native-async-storage/async-storage";
import { CearsiMobile } from "./cearsi-mobile";
export const cearsi = new CearsiMobile({
apiKey: process.env.EXPO_PUBLIC_CEARSI_KEY, // csk_live_...
storage: AsyncStorage,
maxTurns: 20,
});import { useEffect, useState } from "react";
import { View, Text, TextInput, FlatList, Pressable } from "react-native";
import { cearsi } from "../lib/cearsi";
export default function ChatScreen() {
const [messages, setMessages] = useState([]);
const [text, setText] = useState("");
const [busy, setBusy] = useState(false);
useEffect(() => {
const off = cearsi.subscribe(setMessages);
cearsi.load();
return off;
}, []);
async function send() {
const q = text.trim();
if (!q || busy) return;
setText(""); setBusy(true);
try { await cearsi.send(q); }
catch (e) { console.warn(e.message); }
finally { setBusy(false); }
}
return (
<View style={{ flex: 1, padding: 16 }}>
<FlatList
data={messages}
keyExtractor={(_, i) => String(i)}
renderItem={({ item }) => (
<Text style={{ marginVertical: 6, textAlign: item.role === "user" ? "right" : "left" }}>
{item.content}
</Text>
)}
/>
<View style={{ flexDirection: "row", gap: 8 }}>
<TextInput
value={text}
onChangeText={setText}
onSubmitEditing={send}
placeholder="Ask Cearsi about crypto, taxes, or finance…"
style={{ flex: 1, borderWidth: 1, borderRadius: 10, padding: 10 }}
/>
<Pressable onPress={send} disabled={busy}>
<Text style={{ padding: 12 }}>{busy ? "…" : "Send"}</Text>
</Pressable>
</View>
</View>
);
}Source: /sdk/v1/cearsi-mobile.js — ship the key from your own backend for production apps; a bundled key is visible to anyone who unpacks the binary. Restrict it by scope (chat:write) and rotate it from API keys settings.
Embeddable widget
Drop the Cearsi chat bubble onto any site. Create a key in API keys settings, add your domain(s) to Allowed origins, then paste the snippet below into your HTML.
<script
src="https://cearsi.dev/embed/v1/widget.js"
data-key="csk_live_..."
data-title="Ask Cearsi"
data-color="#6d28d9"
defer
></script>The widget is scoped by Allowed origins on the key — Cearsi rejects any browser request whose Origin is not on your allowlist, so a leaked key from your marketing site cannot be reused elsewhere. Configure the allowlist in Settings → API Keys.
MCP endpoint
Cearsi exposes a Model Context Protocol server so Claude, Cursor, ChatGPT, and any custom agent can call its tools directly.
https://cearsi.dev/mcpUses OAuth 2.1 with dynamic client registration — no manual client setup required.
Outbound webhooks
Register an HTTPS endpoint in Settings → API Keys and receive chat.completed events. Each request carries an x-cearsi-signature: t=<timestamp>,v1=<hex> header.
import { createHmac, timingSafeEqual } from "crypto";
function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map(p => p.split("=")));
const expected = createHmac("sha256", secret)
.update(parts.t + "." + rawBody).digest("hex");
const a = Buffer.from(parts.v1); const b = Buffer.from(expected);
if (a.length !== b.length || !timingSafeEqual(a, b)) throw new Error("bad sig");
if (Math.abs(Date.now()/1000 - Number(parts.t)) > 300) throw new Error("stale");
}{
"id": "evt_...",
"event": "chat.completed",
"created_at": "2026-07-18T12:00:00.000Z",
"data": {
"message": { "role": "assistant", "content": "..." },
"input_messages": [ { "role": "user", "content": "..." } ],
"usage": { "prompt_tokens": 128, "completion_tokens": 220 }
}
}Rate limits & fair use
- Max plan: generous per-key request budget suitable for agent loops.
- Domain allowlisting supported per key — set Allowed Origins in Settings → API Keys.
- Revoke a key instantly from the settings page — takes effect on the next request.
