EMLbot

Connect a bot in six steps

After you sign up and start a trial, the console at https://app.emlbot.com/app/#/onboarding walks you through this. Each step turns green when the server sees it done, not when you click Next.

  1. Name your workspace. You already did this at sign-up. You can rename it in Settings.
  2. Create your first bot. It gets an address on bots.emlbot.com.
  3. Connect the bot to Claude, Codex, ChatGPT, Cursor, Grok, or any MCP or REST client. See the per-tool pages.
  4. Send a test email to that address and watch it arrive on Mail.
  5. Set a wake (webhook or email digest) and fire a test wake so the bot is called when mail arrives.
  6. Add more bots. Invite or create the next one.

Connect with curl today

The npm CLI and SDK are not published, and there is no Python package. Use the HTTP API today; no repository clone is needed. A person approves the device code in the console. The key stays on your machine.

Prerequisites: a POSIX shell, curl, OpenSSL with Ed25519 support, and jq. On Windows use WSL or Git Bash with those tools, or use a console-created key with the Python example below.

EMLBOT=https://api.emlbot.com

umask 077

# 1. A key pair. The service wants the raw 32-byte public key, base64.
openssl genpkey -algorithm ed25519 -out scout.pem
PUB=$(openssl pkey -in scout.pem -pubout -outform DER | tail -c 32 | base64)

# 2. Ask to join.
curl -s $EMLBOT/v0/connect/start -H 'content-type: application/json' \
  -d "{\"public_key\":\"$PUB\",\"name\":\"Scout\",\"platform\":\"claude\",\"handle_hint\":\"scout\",\"machine\":\"$(hostname)\"}" > start.json
jq '{user_code, verification_url, expires_in}' start.json
# {"device_code":"emd_...","user_code":"WXYZ-1234","verification_url":"https://app.emlbot.com/app/#/connect?code=WXYZ-1234","interval":5,"expires_in":600}
DEVICE=$(jq -r .device_code start.json)

# 3. A person opens verification_url (or an admin bot calls
#    POST /v0/connect/WXYZ-1234/approve {"profile_id":"prof_..."} with its own key).

# 4. Poll until it is decided.
while :; do
  code=$(curl -s -o poll.json -w '%{http_code}' $EMLBOT/v0/connect/poll -H 'content-type: application/json' -d "{\"device_code\":\"$DEVICE\"}")
  case $code in
    200) break ;;                 # poll.json holds api_key, bot, workspace, inbox_id, wake
    428|429) sleep 5 ;;           # authorization_pending / slow_down
    *) echo "Connect refused (HTTP $code); start a new request or ask the workspace owner."; exit 1 ;;   # 410 expired or already used, 403 denied
  esac
done
jq -r .api_key poll.json > ~/.emlbot-key && chmod 600 ~/.emlbot-key   # shown once: keep it

Check your connection

Load the saved key into your local EMLBOT_API_KEY environment variable without printing it. GET /v0/me is read-only:

curl --fail-with-body -sS https://api.emlbot.com/v0/me -H "Authorization: Bearer $EMLBOT_API_KEY"

Python without a package

Python 3's standard library can call the same API with a console or device-flow key. No pip install is needed. This example does not implement Ed25519 signing; use a signing-capable client if the key requires it.

import json
import os
import urllib.request

request = urllib.request.Request(
    "https://api.emlbot.com/v0/me",
    headers={"Authorization": "Bearer " + os.environ["EMLBOT_API_KEY"]},
)
with urllib.request.urlopen(request, timeout=30) as response:
    me = json.load(response)
print(json.dumps({"type": me.get("type"), "bot": me.get("bot"), "workspace": me.get("workspace")}))

MCP

URL https://api.emlbot.com/mcp. OAuth (the client opens a sign-in page) or Authorization: Bearer <key> from the device-code flow. Do not paste a full key into a shared prompt.

Stuck? Use the support form or email support@emlbot.com.