Docs / Web API

Web API

Send and receive fmsg messages directly from your own code at https://api.fmsg.ai: HTTPS and JSON, plus a WebSocket that tells you when new messages arrive. It's the same API the fmsg.ai web app and MCP server use, so anything they do, your code can do too.

1. Create a sub-address

Your code gets its own fmsg address, a sub-address, and an API key for it.

  1. Sign in at fmsg.ai and open Settings.
  2. Under AI apps, choose Connect with an API key, then a new sub-address (give it a name, such as bot; its address is your address with the name added, e.g. @you_bot@fmsg.ai) or one you have.
  3. Copy the API key. It's shown once. Under Sub-addresses, Create key or Rotate key does the same for one you have.

Keys expire after 30, 90 or 365 days (your choice), and you can rotate or delete them under Sub-addresses. How many sub-addresses you can have depends on your plan.

2. Exchange the key for an access token

Send the API key to /fmsg/token, and only there. You get back an access token that lasts 12 hours:

curl -X POST https://api.fmsg.ai/fmsg/token \
  -H "Authorization: Bearer $FMSG_API_KEY"
{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 43200,
  "expires_at": "2026-10-01T12:00:00Z"
}

Use the access token for every other request, and get a new one before expires_at:

export FMSG_TOKEN=eyJ...
curl https://api.fmsg.ai/fmsg -H "Authorization: Bearer $FMSG_TOKEN"

3. Send and receive

Read your inbox

GET /fmsg lists messages sent to your address, newest first, 20 at a time (up to 100 with ?limit=; page with ?offset=). Each message has its sender, recipients, topic, type, delivery state per recipient, whether you've read it, reactions and attachments. For text, short_text holds the start of the body; fetch the whole body with GET /fmsg/{id}/data.

curl "https://api.fmsg.ai/fmsg?limit=5" -H "Authorization: Bearer $FMSG_TOKEN"

Send a message

Sending takes two steps: create a draft, then send it. from must be your sub-address, and size is the body's length in bytes.

curl -X POST https://api.fmsg.ai/fmsg \
  -H "Authorization: Bearer $FMSG_TOKEN" -H "Content-Type: application/json" \
  -d '{
    "version": 1,
    "from": "@you_bot@fmsg.ai",
    "to": ["@alice@example.com"],
    "topic": "Build finished",
    "type": "text/plain;charset=UTF-8",
    "size": 20,
    "data": "All 42 tests passed."
  }'
# {"id": 1234}

curl -X POST https://api.fmsg.ai/fmsg/1234/send -H "Authorization: Bearer $FMSG_TOKEN"
# {"id": 1234, "time": 1790000000.123, "sha256": "..."}

Between the two steps you can attach files to the draft (POST /fmsg/{id}/attach, a multipart/form-data upload with a file field) or change it (PUT /fmsg/{id}). Once sent, a message can't be edited, recalled or deleted.

Reply

A reply is a message with pid set to the message it replies to, and no topic. Address it to everyone you want to reach, usually the sender and the other recipients.

Hear about new messages

Rather than polling, open a WebSocket to wss://api.fmsg.ai/fmsg/ws with the same Authorization header. Each frame is a JSON event:

{ "type": "new_msg", "data": { "id": 1235, "from": "@alice@example.com", ... } }
Event When
new_msgA message arrives for you. data is the message, as in the inbox list.
deliveredA message you sent was delivered to a recipient, or failed.
recipients_addedSomeone added recipients to a message you're on.
reactionSomeone reacted to a message you're on.

The server pings to keep the connection open; most WebSocket libraries answer automatically. If the connection drops, reconnect and list your inbox to catch up on anything you missed.

Endpoints

All paths are under https://api.fmsg.ai. {id} is a message ID.

Request What it does
POST /fmsg/tokenExchange an API key for an access token
GET /fmsgMessages sent to you, newest first
GET /fmsg/sentMessages you've sent, and drafts
GET /fmsg/wsWebSocket of events
POST /fmsgCreate a draft
GET /fmsg/{id}One message
PUT /fmsg/{id}Change a draft
DELETE /fmsg/{id}Delete a draft
POST /fmsg/{id}/sendSend a draft
POST /fmsg/{id}/readMark a message read
POST /fmsg/{id}/add-toAdd recipients to a message, body {"add_to": ["@carol@example.com"]}
POST /fmsg/{id}/reactSet or clear an emoji reaction
GET /fmsg/{id}/dataDownload the message body
GET /fmsg/{id}/thread/messagesThe thread, from its first message down to this one, as JSON
POST /fmsg/{id}/attachAttach a file to a draft
GET /fmsg/{id}/attach/{filename}Download an attachment
DELETE /fmsg/{id}/attach/{filename}Remove an attachment from a draft

Request and response fields, and every error, are in the fmsg-webapi reference.

Good to know

Security

Troubleshooting

More