Koveh API

Mail Ingest API

Add inbox mail without IMAP. Look and correct API-added rows only. No send.

The Mail Ingest API writes into the same mail_messages table as the IMAP worker, so scraped mail shows up on koveh.com/mail. Use it when IMAP is unavailable or paid.

Base URL

https://api.koveh.com/mail/

Authentication

Authorization: Bearer <api_key> or X-API-Key: <api_key>

api_users.allowed_models must include mail, mail-ingest, or mail-inbox. Admin keys also work.

This API cannot send mail. It can only look, add, and correct rows that were added this way (ingest_source = api). IMAP rows stay read-only.


Endpoints

Health

GET /health — no auth

Accounts

GET /accounts — mailboxes the scraper may file into

List

GET /messages?account=&ingest_source=&since=&q=&limit=&offset=

One message

GET /messages/{id}

Add

POST /messages

Accepts one object, an array, or { "messages": [...] }.

JSON body:

{
  "account": "daniil@koveh.com",
  "subject": "Concert Friday",
  "sender": "Tickets <hello@example.com>",
  "recipient": "daniil@koveh.com",
  "received_at": "2026-08-19T18:00:00Z",
  "body_text": "Doors at 19:00. Hall 2."
}

If message_id is missing, the API stores a stable api:<sha256> id so the same scrape does not duplicate.

Correct

PATCH /messages/{id} — only when ingest_source is api. IMAP mail returns 409.


Provenance

ColumnMeaning
ingest_sourceimap or api
ingested_atwhen the row was first written
ingested_byAPI user email that added it

Example

curl -X POST "https://api.koveh.com/mail/messages" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account": "daniil@koveh.com",
    "subject": "Concert Friday",
    "sender": "Tickets <hello@example.com>",
    "received_at": "2026-08-19T18:00:00Z",
    "body_text": "Doors at 19:00."
  }'

On this page