SDKs
Typed clients for TypeScript and Python.
Install
npm
npm install carlyemail
pip
pip install carlyemail
Every endpoint, in both languages.
A first inbox
TypeScript
import { CarlyEmail } from "carlyemail";
const carly = new CarlyEmail(); // reads CARLYEMAIL_API_KEY
const inbox = await carly.inboxes.create({ username: "hello" });
await carly.messages.send(inbox.email, {
to: ["you@example.com"],
subject: "Hello",
text: "From an agent.",
});
Python
from carlyemail import CarlyEmail
carly = CarlyEmail() # reads CARLYEMAIL_API_KEY
inbox = carly.inboxes.create({"username": "hello"})
carly.messages.send(
inbox["email"],
{"to": ["you@example.com"], "subject": "Hello", "text": "From an agent."},
)
Resources on the client: agent, auth, billing, inboxes, messages,
threads, drafts, lists, domains, apiKeys / api_keys, metrics,
pods, organizations, inboxEvents / inbox_events, webhooks.
Reading and replying
TypeScript
const { messages } = await carly.messages.list(inbox.email, { limit: 10 });
for (const message of messages) {
// `extracted_text` is the new content with the quoted chain stripped, which
// is what you want to hand a model. `text` is the whole thing.
const body = message.extracted_text ?? message.text ?? "";
await carly.messages.reply(inbox.email, message.message_id, {
text: answer(body),
});
}
Python
for message in carly.messages.list(inbox["email"], limit=10)["messages"]:
body = message.get("extracted_text") or message.get("text") or ""
carly.messages.reply(
inbox["email"], message["message_id"], {"text": answer(body)}
)
Reply to a message rather than composing a new one and it lands in the
sender's existing thread — In-Reply-To and References are set for you.
Errors
Errors carry the message, the thing that clears it, and a documentation link.
TypeScript
import { CarlyEmailError } from "carlyemail";
try {
await carly.inboxes.create({ username: "hello" });
} catch (error) {
if (error instanceof CarlyEmailError) {
console.log(error.status, error.code); // 429 inbox_limit_reached
console.log(error.fix); // Upgrade the plan, or delete…
console.log(error.docs);
}
}
Python
from carlyemail import CarlyEmailError
try:
carly.inboxes.create({"username": "hello"})
except CarlyEmailError as error:
print(error.status, error.code) # 429 inbox_limit_reached
print(error.fix) # Upgrade the plan, or delete…
print(error.docs)
See errors for every code.
Configuration
The key comes from CARLYEMAIL_API_KEY unless you pass one.
TypeScript
new CarlyEmail({
apiKey: process.env.MY_KEY,
baseUrl: "http://localhost:8000", // pointing at a local API
fetch: myFetch, // a proxy, or retries
});
Python
CarlyEmail(
api_key=os.environ["MY_KEY"],
base_url="http://localhost:8000",
timeout=60.0,
)
TypeScript has no dependencies and runs in Node, the browser, a worker and on
the edge. Python needs httpx.
The CLI comes with it
npm install carlyemail also puts the CLI on your path.
npx carlyemail signup
Another language
Generate a client from the published spec.
npx @hey-api/openapi-ts -i https://docs.carlyemail.com/openapi.json -o ./carlyemail
openapi-generator-cli generate -i https://docs.carlyemail.com/openapi.json -g go -o ./carlyemail