Get started

Quickstart

By the end of this page you'll have an API key, a connected inbox, and a real email out the door — all driven by HTTP. Total time: about five minutes.

1. Create a workspace and API key

Sign in with a magic link. The first time you log in, Clement creates a workspace for you. Open Settings → API keys and click Create key.

Pick the write scope to start — that's enough to create contacts and sends, but not to revoke other keys or rotate webhooks. The secret is shown once; copy it somewhere safe. If you lose it, rotate.

export CLEMENT_API_KEY=cl_live_a1b2c3d4e5f6...

2. Connect an inbox

Sends always go through a connected inbox. For Gmail and Outlook, OAuth consent has to happen in a real browser session — call:

curl -X POST "https://api.clement.so/v1/inboxes/google/connect_link" \
  -H "Authorization: Bearer $CLEMENT_API_KEY"

The response carries a one-time URL. Open it in a browser, sign in to the Google account you want to send from, and grant the requested scopes. Once you land on the success page, the inbox is ready — list inboxes to grab its ID:

curl "https://api.clement.so/v1/inboxes" \
  -H "Authorization: Bearer $CLEMENT_API_KEY"

For SMTP/IMAP accounts, no browser handoff is required — see the inboxes reference for the credential-based path.

3. Send your first email

POST /v1/sends is the primitive. Replace the inbox ID with yours, then run the call. The Idempotency-Key header is required — generate any UUID; same UUID + same body within 24 hours is safe to retry.

curl

curl -X POST "https://api.clement.so/v1/sends" \
  -H "Authorization: Bearer $CLEMENT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  --data '{
    "inbox_id": "inb_01HZ8X3J9K7P2QV6R5N4M3T2L1",
    "to": [{"email": "alice@example.com", "name": "Alice"}],
    "subject": "Quick question about your stack",
    "body_text": "Hi {{first_name}}, would love to chat — does Tuesday work?",
    "variables": {"first_name": "Alice"}
  }'

TypeScript

import { Clement } from "@clement/sdk";

const c = new Clement({ apiKey: process.env.CLEMENT_API_KEY! });

const send = await c.sends.create(
  {
    inbox_id: "inb_01HZ8X3J9K7P2QV6R5N4M3T2L1",
    to: [{ email: "alice@example.com", name: "Alice" }],
    subject: "Quick question about your stack",
    body_text: "Hi {{first_name}}, would love to chat — does Tuesday work?",
    variables: { first_name: "Alice" },
  },
  { idempotencyKey: crypto.randomUUID() },
);

console.log(send.id, send.state);

The response is the full Send resource with state scheduled. The worker picks it up, sends via Gmail, and transitions through sending → sent. The whole thing takes a second or two.

4. Watch the event fire

Every state transition emits an event. To watch them without setting up a webhook endpoint, poll /v1/events filtered to the send:

curl "https://api.clement.so/v1/events?resource_id=$SEND_ID" \
  -H "Authorization: Bearer $CLEMENT_API_KEY"

You'll see send.scheduled, send.sending, send.sent. Once the recipient opens or replies you'll also see message.opened, message.clicked, message.replied.

For real integrations, point a webhook endpoint at POST /v1/webhooks instead of polling — see the webhooks guide.

Next steps