Developers

An API for email
you actually own.

Everything the apps do, you can do too. 60 REST endpoints, described by a single OpenAPI 3.1 contract, with a generated TypeScript client we use ourselves on web and mobile. No scraping, no reverse-engineering — it's the real thing.

Base URL
api.anfon.co/v1
Auth
Bearer token or session cookie
Format
JSON · OpenAPI 3.1
Surface
60 endpoints · 16 groups

Authentication

Sign in with POST /v1/auth/login to start a session. Browser clients use a secure session cookie; mobile and server-to-server clients use a bearer token and rotate it with POST /v1/auth/refresh. There is no open relay — every send is authenticated and attributed to your account.

# Authenticate, then list the threads in a mailbox
curl -s https://api.anfon.co/v1/auth/login \
  -H 'content-type: application/json' \
  -d '{"email":"you@your-domain.au","password":"••••••••"}'

curl -s https://api.anfon.co/v1/mailboxes/$MAILBOX/threads \
  -H "authorization: Bearer $TOKEN"

Typed client

We publish a TypeScript client generated straight from the OpenAPI spec — the same one powering our web and mobile apps. Point it at the spec and you get fully-typed calls and responses for every endpoint below.

import { listThreads, addNote } from '@anfon/api-client';

const { data } = await listThreads({
  client, path: { mailbox_id }, query: { folder: 'inbox' },
});

// Collaborate: drop an internal note and @mention a teammate
await addNote({
  client, path: { thread_id },
  body: { body: 'Looping you in @sam', mentioned_user_ids: [samId] },
});

Endpoints

The full surface, grouped. Open any group for the routes; hit the interactive reference for request/response schemas and a live try-it console. A lock means the endpoint requires authentication.

Auth & sessions4
POST/v1/auth/loginAuthenticate and start a session
POST/v1/auth/logoutRevoke the current session
POST/v1/auth/refreshRotate a refresh token (mobile/api)
POST/v1/auth/signupCreate an account + owner and start a session
Account2
GET/v1/accountAccount details
GET/v1/meCurrent user + accessible mailboxes
Users & directory3
GET/v1/directoryList account people for @mention pickers
GET/v1/usersList account users (owner)
POST/v1/usersCreate a user (owner)
Domains7
GET/v1/domainsList domains
POST/v1/domainsOrder a domain + auto-provision DNS/DKIM (owner)
GET/v1/domains/availabilityCheck domain availability + price
POST/v1/domains/connectConnect a domain you already own (delegate NS or add records; owner)
DELETE/v1/domains/{domain_id}Remove a domain + its DNS/DKIM (owner)
GET/v1/domains/{domain_id}/setupOnboarding instructions: nameservers (delegated) or records to add (external)
POST/v1/domains/{domain_id}/verifyCheck DNS and activate a connected domain (owner)
DNS records3
GET/v1/domains/{domain_id}/recordsList DNS records for a domain
POST/v1/domains/{domain_id}/recordsCreate a custom DNS record (owner)
DELETE/v1/domains/{domain_id}/records/{record_id}Delete a custom DNS record (owner)
Mailboxes & aliases9
GET/v1/mailboxesList accessible mailboxes
POST/v1/mailboxesCreate a mailbox (owner)
PATCH/v1/mailboxes/{mailbox_id}Set whether a mailbox is the domain catch-all (owner)
GET/v1/mailboxes/{mailbox_id}/aliasesList a mailbox's alias addresses
POST/v1/mailboxes/{mailbox_id}/aliasesAdd an alias address that delivers into a mailbox
DELETE/v1/mailboxes/{mailbox_id}/aliases/{alias_id}Remove an alias
GET/v1/mailboxes/{mailbox_id}/membersList co-collaborators on a mailbox
POST/v1/mailboxes/{mailbox_id}/membersAssign a user to a mailbox (owner)
DELETE/v1/mailboxes/{mailbox_id}/members/{user_id}Remove a user from a mailbox (owner)
Folders1
GET/v1/mailboxes/{mailbox_id}/foldersList a mailbox's folders + unread counts
Threads & triage9
GET/v1/mailboxes/{mailbox_id}/thread-countsTriage counts for a mailbox (open/snoozed/closed/assigned/unread)
GET/v1/mailboxes/{mailbox_id}/threadsList threads in a mailbox
GET/v1/threadsCross-inbox threads (All Open / Assigned to me)
GET/v1/threads/countsCross-inbox counts (open + assigned to me)
GET/v1/threads/{thread_id}Get a single thread (status/assignee/counts)
PATCH/v1/threads/{thread_id}Set thread status (open/snoozed/closed)
POST/v1/threads/{thread_id}/assignAssign a thread to a mailbox member
GET/v1/threads/{thread_id}/messagesMessages in a thread
GET/v1/threads/{thread_id}/sharesList the users a thread is shared with
Messages4
POST/v1/messagesCompose + send a message (authenticated; no open relay)
PATCH/v1/messages/{message_id}Update message (seen/flagged/move)
GET/v1/messages/{message_id}/attachmentsList a message's attachments (metadata + ids)
GET/v1/messages/{message_id}/bodyDecrypted message body + headers
Internal notes2
GET/v1/threads/{thread_id}/notesList a thread's internal notes
POST/v1/threads/{thread_id}/notesAdd an internal note (not emailed)
Mentions3
GET/v1/mentionsList the caller's @mentions (+ unread count)
POST/v1/mentions/read-allMark all the caller's mentions read
POST/v1/mentions/{mention_id}/readMark a mention read
Tags6
GET/v1/mailboxes/{mailbox_id}/tagsList a mailbox's tags
POST/v1/mailboxes/{mailbox_id}/tagsCreate a tag on a mailbox
DELETE/v1/mailboxes/{mailbox_id}/tags/{tag_id}Delete a tag from a mailbox
GET/v1/threads/{thread_id}/tagsTags applied to a thread
POST/v1/threads/{thread_id}/tagsApply a tag to a thread
DELETE/v1/threads/{thread_id}/tags/{tag_id}Remove a tag from a thread
Search1
GET/v1/searchHybrid FTS + semantic search
Devices & push3
POST/v1/devicesRegister an Expo push token
DELETE/v1/devices/{device_id}Unregister a device
PATCH/v1/devices/{device_id}Update device mute / quiet-hours
Billing2
POST/v1/billing/checkoutStart a subscription checkout (owner)
GET/v1/billing/entitlementCurrent subscription entitlement
System1
GET/v1/healthLiveness/health probe

Building something with it? We'd love to hear about it — and we're adding IMAP/JMAP and webhooks to the roadmap. Tell us what you need at our contact page.