mailkh. API

Create disposable inboxes, read their mail, and generate throwaway test identities — programmatically. REST, JSON, one API key.

Base URL https://mailkh.com/v1 · all responses are JSON · all requests need an API key.

Authentication

Get a key in the mailkh appAPINew key. It's shown once — store it safely. Send it on every request:

Authorization: Bearer mk_live_xxxxxxxxxxxx
# or
X-API-Key: mk_live_xxxxxxxxxxxx

Keys are stored only as a SHA-256 hash. Lost or leaked a key? Revoke it in the app and make a new one.

Limits

TierInbox creationInbox lifespanProfiles / request
Free3 per rolling 24hAuto-deleted after 24h10
ProUnlimitedPermanent100

Exceeding the free limit returns 429 with {"code":"daily_limit"}. Upgrade to Pro in the app for unlimited, permanent inboxes.

Endpoints

POST /v1/inboxes

Create a temp inbox. Body is optional — omit it for a random address.

FieldTypeNotes
localstringOptional. Custom local part (before @). Random if omitted.
domainstringOptional. Must be a supported domain; defaults to the first one.
curl -X POST https://mailkh.com/v1/inboxes \
  -H "Authorization: Bearer mk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"local":"signup-test"}'

# 201
{ "id": "…", "address": "signup-test@mailkh.com", "expires_at": 1750000086400000 }

expires_at is Unix ms, or null for permanent (Pro).

GET /v1/inboxes

List your active inboxes.

curl https://mailkh.com/v1/inboxes -H "Authorization: Bearer mk_live_xxx"

{ "inboxes": [ { "id":"…", "address":"signup-test@mailkh.com", "created_at":…, "expires_at":… } ] }

GET /v1/inboxes/:address/messages

List messages in an inbox (newest first). Poll this to wait for mail.

curl https://mailkh.com/v1/inboxes/signup-test@mailkh.com/messages \
  -H "Authorization: Bearer mk_live_xxx"

{ "messages": [ { "id":"…", "sender":"no-reply@x.com", "subject":"Verify", "received_at":…, "attachment_count":0 } ] }

GET /v1/messages/:id

Get one message in full, including body.

curl https://mailkh.com/v1/messages/MESSAGE_ID -H "Authorization: Bearer mk_live_xxx"

{ "id":"…", "recipient":"…", "sender":"…", "subject":"…", "text_body":"…", "html_body":"…", "received_at":… }

DELETE /v1/inboxes/:address · DELETE /v1/messages/:id

Delete an inbox (and its mail) or a single message. Returns { "ok": true }.

GET /v1/profiles

Generate one or more throwaway social profiles — name, sex, date of birth, place of birth, address, phone, username and a strong password. Pure data, nothing is stored. Available on every valid key.

QueryTypeNotes
countintOptional. How many profiles. Default 1. Max 10 on Free, 100 on Pro — requests above the cap are clamped (Free responses include an upgrade hint).
countrystringOptional. One of US UK CA AU FR DE JP KH. Default US. Drives names, address format and phone.
curl "https://mailkh.com/v1/profiles?count=1&country=KH" \
  -H "Authorization: Bearer mk_live_xxx"

{
  "count": 1,
  "country": "KH",
  "profiles": [
    {
      "country": "Cambodia", "countryCode": "KH", "sex": "male",
      "firstName": "Vibol", "lastName": "Heng", "fullName": "Vibol Heng",
      "dateOfBirth": "2002-05-04", "age": 24, "placeOfBirth": "Pursat",
      "address": "No. 91, Street 271, Sangkat Chroy Changvar, Khan 7 Makara, Phnom Penh 12048",
      "phone": "+855 69 168 486", "username": "vibol.heng86", "password": "8?@pj#&NhhC&V2"
    }
  ]
}

Dates are ISO yyyy-mm-dd; usernames are ASCII-safe. An unknown country returns 400 with the list of valid codes.

Errors

StatusMeaning
400Bad request (e.g. unknown country on /v1/profiles)
401Missing or invalid API key
404Inbox or message not found (or not yours)
409Address already taken
429Daily free limit reached

Typical flow

1. POST /v1/inboxes            → get { address }
2. show / use that address     → e.g. sign up somewhere with it
3. poll GET …/:address/messages → until a message appears
4. GET /v1/messages/:id        → read the code / link
5. (optional) DELETE when done