API docs

Sign in to create an API key, claim addresses, and read mail that only your key can see. Base URL: https://panda-mail.net

Create a key

Sign in or sign up first. Save the key — it is only shown once.

Quickstart

Create a key, claim an address, then poll messages. Copy a snippet and swap in your key.

import time
import requests

BASE = "https://panda-mail.net"

# 1) Create a key (save it — shown once)
key = requests.post(f"{BASE}/api/v1/keys").json()["key"]
headers = {"Authorization": f"Bearer {key}"}

# 2) Create a mailbox
box = requests.post(
    f"{BASE}/api/v1/mailboxes",
    headers=headers,
    json={"domain": "thedigitalworld.me"},
).json()
address = box["address"]
print("Address:", address)

# 3) Poll for mail
# code = OTP when present; Discord verify uses a link in body (code is null)
while True:
    data = requests.get(
        f"{BASE}/api/v1/messages",
        headers=headers,
        params={"address": address},
    ).json()
    for msg in data.get("messages", []):
        print(msg["from"], "|", msg["subject"])
        if msg.get("code"):
            print("OTP:", msg["code"])
        else:
            print(msg.get("body") or "")
    time.sleep(5)

Needs pip install requests

Auth

Send your key on every request after create:

Authorization: Bearer pm_your_key_here

Keys are shown once. Lost key = create a new key and new mailboxes.

Endpoints

POST /api/v1/keys

Create an API key. Requires a signed-in session (Sign in / Sign up). Rate limited.

{
  "key": "pm_...",
  "prefix": "pm_abcdef12"
}

GET /api/v1/domains

Public list of allowed domains.

{
  "domains": ["thedigitalworld.me", "mintpost.surf"]
}

POST /api/v1/mailboxes

Create a mailbox under your key. Optional body: { "domain": "thedigitalworld.me" }. Leave local out to get a random name.

{
  "address": "abc123@thedigitalworld.me",
  "local": "abc123",
  "domain": "thedigitalworld.me",
  "created_at": 1730000000000
}

GET /api/v1/mailboxes

List mailboxes owned by your key.

GET /api/v1/messages?address=

List messages for an address you own. Other people’s addresses return 403. Triggers an IMAP poll for that address.

code is only set when the mail contains an OTP. Discord verify mail is a link, so code is null — use body / html for the verify URL.

{
  "address": "k7m2xq9p@thedigitalworld.me",
  "messages": [
    {
      "id": "msg_01hxyz",
      "from": "noreply@discord.com",
      "subject": "Verify email address for Discord",
      "body": "Hey,\n\nThanks for registering for an account on Discord! Before we get started, we just need to confirm that this is you. Click below to verify your email address:\n\nhttps://click.discord.com/ls/click?upn=example\n",
      "code": null,
      "received_at": 1730000000000
    },
    {
      "id": "msg_01habc",
      "from": "noreply@example-app.com",
      "subject": "Your verification code",
      "body": "Your verification code is 482917. It expires in 10 minutes.",
      "code": "482917",
      "received_at": 1730000000500
    }
  ]
}

GET /api/v1/messages/:id

Fetch one message (includes html when available).

DELETE /api/v1/mailboxes/:address

Delete a mailbox you own (URL-encode the address).

curl -X DELETE "https://panda-mail.net/api/v1/mailboxes/abc123%40thedigitalworld.me" \
  -H "Authorization: Bearer pm_..."

Python one-liner poll

After you have a key + address:

python -c "import requests; print(requests.get('https://panda-mail.net/api/v1/messages', headers={'Authorization':'Bearer pm_...'}, params={'address':'you@thedigitalworld.me'}).json())"

Privacy

Each mailbox is locked to the API key that created it. Guessing an address without the key does not reveal messages.

← Back to inbox