Forward Email Messages API

Alias messages management endpoints (IMAP/POP3) >[!NOTE] > Unlike other API endpoints, these require [Authentication](#description/authentication) "username" equal to the alias username and "password" equal to the alias generated password as Basic Authorization headers. >[!TIP] > These endpoints provide comprehensive message management with advanced search capabilities. You can search by folder, flags, content, headers, date ranges, size, and more. Messages can be created using standard Nodemailer format and support moving between folders and flag management. Please ensure that you have followed setup instructions for your domain. These instructions can be found in our FAQ section [Do you support receiving email with IMAP?](/faq#do-you-support-receiving-email-with-imap).

Operations 5

GET /v1/messages List and search messages #
POST /v1/messages Create message #
GET /v1/messages/{id} Retrieve message #
PUT /v1/messages/{id} Update message #
DELETE /v1/messages/{id} Delete message #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/forward-email:forward-email-messages-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

forward-email-messages-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Forward Email Messages API
  description: 'Welcome to the comprehensive API documentation for Forward Email. This API allows you to manage email forwarding, domains, aliases, outbound emails, and more programmatically.


    ## Key Features

    * **Domain Management:** Create, retrieve, update, delete, and verify domains.

    * **Alias Management:** Manage email aliases, including creation, updates, and recipient management.

    * **Outbound SMTP:** Send emails via SMTP, manage limits, and track sent emails.

    * **Account & Logs:** Manage your account details and download activity logs.

    * **Security:** Encrypt TXT records and manage domain members/invites.

    * **CardDAV Contacts:** Full CRUD operations for contact management with vCard support.

    * **CalDAV Calendars:** Complete calendar management with timezone and color support.

    * **IMAP/POP3 Messages:** Comprehensive message management with advanced search capabilities.

    * **IMAP/POP3 Folders:** Full folder management including creation, renaming, and deletion.


    ## Authentication

    Most endpoints require authentication using your **API Key**. Provide the API Key as the `username` in the Basic Authentication header, leaving the password empty.


    ```http

    Authorization: Basic QVBJX1RPS0VOOg==

    ```

    (Replace `API_TOKEN` with your actual key before Base64 encoding)


    Endpoints related to **Alias Contacts, Calendars, Messages, and Folders** require a generated alias username and password for Basic Authentication.


    ## Errors

    The API uses standard HTTP status codes to indicate success or failure. Error responses include a JSON body with a `message` field detailing the error.


    | Status Code | Meaning |

    |-------------|---------------------|

    | 200 | OK |

    | 400 | Bad Request |

    | 401 | Unauthorized |

    | 403 | Forbidden |

    | 404 | Not Found |

    | 409 | Conflict |

    | 412 | Precondition Failed |

    | 429 | Too Many Requests |

    | 500 | Internal Server Error|

    | 501 | Not Implemented |

    | 502 | Bad Gateway |

    | 503 | Service Unavailable |

    | 504 | Gateway Time-out |


    *If you encounter a `5xx` error, please contact api@forwardemail.net.*


    ## Localization

    API responses are translated based on the user''s detected locale or the `Accept-Language` header. Over 25 languages are supported.


    ## Pagination

    Endpoints returning lists support pagination via query parameters.


    | Parameter | Type | Optional | Description | Default | Constraints |

    |--------------|---------|----------|-----------------------------------------------------------------------------|---------|--------------------|

    | `page` | Integer | Yes | Page number to retrieve. | 1 | `>= 1` |

    | `limit` | Integer | Yes | Number of results per page. | 25 | `>= 1`, `<= 100` |

    | `pagination` | Boolean | Yes | Opt-in to pagination behavior (required before Nov 1st, 2024 for some endpoints). | false | |


    **Pagination Headers:**

    * `X-Page-Count`: Total page count.

    * `X-Page-Current`: Current page number.

    * `X-Page-Size`: Number of items on the current page.

    * `X-Item-Count`: Total number of items across all pages.

    * `Link`: Navigation links (prev, next, first, last).


    **Example:**

    ```bash

    curl "https://api.forwardemail.net/v1/domains?page=2&limit=20&pagination=true" \

    -u API_TOKEN:

    ```


    ## Recommended Libraries

    * **Ruby:** Faraday

    * **Python:** requests

    * **Java:** OkHttp

    * **PHP:** Guzzle

    * **JavaScript/Node.js:** superagent (Maintained by Forward Email)

    * **Go:** `net/http`

    * **.NET:** RestSharp'
  version: 1.0.0
  contact:
    name: Forward Email Support
    url: https://forwardemail.net
    email: api@forwardemail.net
servers:
- url: https://api.forwardemail.net
  description: Forward Email API Server
tags:
- name: Messages
  description: 'Alias messages management endpoints (IMAP/POP3)


    >[!NOTE]

    > Unlike other API endpoints, these require Authentication "username" equal to the alias username and "password" equal to the alias generated password as Basic Authorization headers.


    >[!TIP]

    > These endpoints provide comprehensive message management with advanced search capabilities. You can search by folder, flags, content, headers, date ranges, size, and more. Messages can be created using standard Nodemailer format and support moving between folders and flag management.


    Please ensure that you have followed setup instructions for your domain.

    These instructions can be found in our FAQ section Do you support receiving email with IMAP?.'
paths:
  /v1/messages:
    get:
      tags:
      - Messages
      summary: List and search messages
      description: Retrieve a list of messages with advanced search and filtering capabilities. This endpoint supports pagination and comprehensive search across message content, headers, flags, and metadata. You can search by folder, flags, content, headers, date ranges, size, and more.
      operationId: listMessages
      security:
      - AliasAuth: []
      parameters:
      - $ref: '#/components/parameters/page'
      - $ref: '#/components/parameters/limit'
      - name: folder
        in: query
        description: Filter messages by folder path
        schema:
          type: string
      - name: is_unread
        in: query
        description: Filter by read status
        schema:
          type: boolean
      - name: is_flagged
        in: query
        description: Filter by flagged status
        schema:
          type: boolean
      - name: is_deleted
        in: query
        description: Filter by deleted status
        schema:
          type: boolean
      - name: is_draft
        in: query
        description: Filter by draft status
        schema:
          type: boolean
      - name: is_junk
        in: query
        description: Filter by junk/spam status
        schema:
          type: boolean
      - name: is_copied
        in: query
        description: Filter by copied status
        schema:
          type: boolean
      - name: is_encrypted
        in: query
        description: Filter by encryption status (PGP/MIME or S/MIME)
        schema:
          type: boolean
      - name: is_searchable
        in: query
        description: Filter by searchable status
        schema:
          type: boolean
      - name: is_expired
        in: query
        description: Filter by expired status
        schema:
          type: boolean
      - name: has_attachments
        in: query
        description: Filter by attachment presence
        schema:
          type: boolean
      - name: has_attachment
        in: query
        description: Filter by attachment presence (alias for has_attachments)
        schema:
          type: boolean
      - name: subject
        in: query
        description: Search in message subject
        schema:
          type: string
      - name: body
        in: query
        description: Search in message body/text
        schema:
          type: string
      - name: text
        in: query
        description: Search in message text (alias for body)
        schema:
          type: string
      - name: headers
        in: query
        description: Search in all message headers
        schema:
          type: string
      - name: message_id
        in: query
        description: Search by Message-ID header
        schema:
          type: string
      - name: search
        in: query
        description: General search across headers and text
        schema:
          type: string
      - name: q
        in: query
        description: General search (alias for search)
        schema:
          type: string
      - name: since
        in: query
        description: Filter messages since this date (ISO 8601 format)
        schema:
          type: string
          format: date-time
      - name: before
        in: query
        description: Filter messages before this date (ISO 8601 format)
        schema:
          type: string
          format: date-time
      - name: min_size
        in: query
        description: Filter messages with minimum size in bytes
        schema:
          type: integer
      - name: max_size
        in: query
        description: Filter messages with maximum size in bytes
        schema:
          type: integer
      - name: from
        in: query
        description: Search by From header
        schema:
          type: string
      - name: to
        in: query
        description: Search by To header
        schema:
          type: string
      - name: cc
        in: query
        description: Search by CC header
        schema:
          type: string
      - name: bcc
        in: query
        description: Search by BCC header
        schema:
          type: string
      - name: date
        in: query
        description: Search by Date header
        schema:
          type: string
      - name: reply-to
        in: query
        description: Search by Reply-To header
        schema:
          type: string
      - name: lightweight
        in: query
        required: false
        schema:
          type: string
          enum:
          - 'true'
          - 'false'
          default: 'false'
        description: When set to "true", returns metadata-only responses without nodemailer or raw fields. This significantly improves performance by skipping full MIME tree reconstruction and attachment body fetching. Useful for building message lists where only metadata (subject, flags, dates, folder, size) is needed.
      responses:
        '200':
          description: Messages retrieved successfully
          headers:
            X-Page-Count:
              description: Total number of pages
              schema:
                type: integer
            X-Page-Current:
              description: Current page number
              schema:
                type: integer
            X-Page-Size:
              description: Number of items on current page
              schema:
                type: integer
            X-Item-Count:
              description: Total number of items
              schema:
                type: integer
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Message'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      tags:
      - Messages
      summary: Create message
      description: Create/append a new message to a folder. This endpoint accepts standard Nodemailer message format and allows you to specify the target folder, initial flags, and labels. If the target folder doesn't exist, it will be created automatically.
      operationId: createMessage
      security:
      - AliasAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MessageInput'
      responses:
        '201':
          description: Message created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v1/messages/{id}:
    get:
      tags:
      - Messages
      summary: Retrieve message
      description: Retrieve a specific message by its ID. By default, the response includes the parsed Nodemailer object and raw message content. You can control what's included using query parameters.
      operationId: retrieveMessage
      security:
      - AliasAuth: []
      parameters:
      - $ref: '#/components/parameters/messageId'
      - name: eml
        in: query
        description: Return raw EML format instead of JSON
        schema:
          type: boolean
          default: false
      - name: nodemailer
        in: query
        description: Include parsed Nodemailer object
        schema:
          type: boolean
          default: true
      - name: attachments
        in: query
        description: Include attachments in Nodemailer object
        schema:
          type: boolean
          default: true
      - name: raw
        in: query
        description: Include raw message content
        schema:
          type: boolean
          default: true
      responses:
        '200':
          description: Message retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
            message/rfc822:
              description: Raw EML format (when ?eml=true)
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    put:
      tags:
      - Messages
      summary: Update message
      description: Update an existing message. You can modify the message flags, labels, or move it to a different folder. If the target folder doesn't exist, it will be created automatically.
      operationId: updateMessage
      security:
      - AliasAuth: []
      parameters:
      - $ref: '#/components/parameters/messageId'
      - name: eml
        in: query
        description: Return raw EML format instead of JSON
        schema:
          type: boolean
          default: false
      - name: lightweight
        in: query
        required: false
        schema:
          type: string
          enum:
          - 'true'
          - 'false'
          default: 'false'
        description: When set to "true", returns metadata only, without nodemailer or raw fields. Skips rebuilding the full message, so flag and label changes respond quickly.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MessageUpdateInput'
      responses:
        '200':
          description: Message updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
            message/rfc822:
              description: Raw EML format (when ?eml=true)
              schema:
                type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      tags:
      - Messages
      summary: Delete message
      description: Delete a specific message permanently. This action cannot be undone and will permanently remove the message from storage. Unlike IMAP clients which typically move messages to Trash, this endpoint performs a hard delete.
      operationId: deleteMessage
      security:
      - AliasAuth: []
      parameters:
      - $ref: '#/components/parameters/messageId'
      responses:
        '200':
          description: Message deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  schemas:
    Message:
      type: object
      required:
      - id
      - root_id
      - folder_id
      - folder_path
      - thread_id
      - header_message_id
      - is_unread
      - is_flagged
      - is_deleted
      - is_draft
      - is_junk
      - is_copied
      - is_encrypted
      - is_searchable
      - is_expired
      - has_attachment
      - retention_date
      - internal_date
      - header_date
      - subject
      - flags
      - labels
      - size
      - uid
      - modseq
      - transaction
      - remote_address
      - created_at
      - updated_at
      - object
      properties:
        id:
          type: string
          description: Message ID
        root_id:
          type: string
          description: Root message ID for threading
        folder_id:
          type: string
          description: Folder ID containing the message
        folder_path:
          type: string
          description: Folder path containing the message
        thread_id:
          type: string
          description: Thread ID for conversation grouping
        header_message_id:
          type: string
          description: Message-ID header value
        is_unread:
          type: boolean
          description: Whether message is unread
        is_flagged:
          type: boolean
          description: Whether message is flagged
        is_deleted:
          type: boolean
          description: Whether message is deleted
        is_draft:
          type: boolean
          description: Whether message is a draft
        is_junk:
          type: boolean
          description: Whether message is junk/spam
        is_copied:
          type: boolean
          description: Whether message is copied
        is_encrypted:
          type: boolean
          description: Whether message is encrypted (PGP/MIME or S/MIME)
        is_searchable:
          type: boolean
          description: Whether message is searchable
        is_expired:
          type: boolean
          description: Whether message is expired
        has_attachment:
          type: boolean
          description: Whether message has attachments
        retention_date:
          type:
          - string
          - 'null'
          format: date-time
          description: Message retention date
        internal_date:
          type: string
          format: date-time
          description: Internal date (IMAP)
        header_date:
          type: string
          format: date-time
          description: Date from message headers
        subject:
          type: string
          description: Message subject
        flags:
          type: array
          items:
            type: string
          description: IMAP flags
        labels:
          type: array
          items:
            type: string
          description: User-defined labels (lowercase, max 10)
          example:
          - work
          - important
          - follow-up
        size:
          type: integer
          description: Message size in bytes
        uid:
          type: integer
          description: IMAP UID
        modseq:
          type: integer
          description: Modification sequence
        transaction:
          type: string
          description: Transaction type
        remote_address:
          type: string
          description: Remote IP address
        created_at:
          type: string
          format: date-time
          description: Message creation timestamp
        updated_at:
          type: string
          format: date-time
          description: Message last update timestamp
        nodemailer:
          type: object
          description: Parsed message object (included by default, set ?nodemailer=false to exclude)
        raw:
          type: string
          description: Raw message content (included by default, set ?raw=false to exclude)
        object:
          type: string
          enum:
          - message
      example:
        id: message123
        root_id: root123
        folder_id: folder123
        folder_path: INBOX
        thread_id: thread123
        header_message_id: <message123@example.com>
        is_unread: true
        is_flagged: false
        is_deleted: false
        is_draft: false
        is_junk: false
        is_copied: false
        is_encrypted: false
        is_searchable: true
        is_expired: false
        has_attachment: false
        retention_date: null
        internal_date: '2025-01-01T00:00:00.000Z'
        header_date: '2025-01-01T00:00:00.000Z'
        subject: Test Message
        flags:
        - \Seen
        size: 1024
        uid: 1
        modseq: 1
        transaction: API
        remote_address: 127.0.0.1
        created_at: '2025-01-01T00:00:00.000Z'
        updated_at: '2025-01-01T00:00:00.000Z'
        object: message
    MessageInput:
      type: object
      properties:
        from:
          type: string
          format: email
          description: Sender email address
        to:
          oneOf:
          - type: string
          - type: array
            items:
              type: string
              format: email
          description: Recipient email addresses
        cc:
          oneOf:
          - type: string
          - type: array
            items:
              type: string
              format: email
          description: CC recipient email addresses
        bcc:
          oneOf:
          - type: string
          - type: array
            items:
              type: string
              format: email
          description: BCC recipient email addresses
        subject:
          type: string
          description: Message subject
        text:
          type: string
          description: Plain text content
        html:
          type: string
          description: HTML content
        attachments:
          type: array
          items:
            type: object
          description: Message attachments (Nodemailer format)
        folder:
          type: string
          description: Target folder (defaults to INBOX)
        flags:
          oneOf:
          - type: string
          - type: array
            items:
              type: string
          description: IMAP flags to set on the message
        labels:
          oneOf:
          - type: string
          - type: array
            items:
              type: string
          description: User-defined labels to set on the message. Can be a single label string or an array of labels. Labels must start with a letter, digit, backslash, or dollar sign, and can contain word characters, dots, and hyphens. Maximum of 10 labels per message. Labels are case-insensitive and will be stored in lowercase.
          example:
          - work
          - important
    Error:
      type: object
      required:
      - message
      properties:
        message:
          type: string
          description: Error message
    MessageUpdateInput:
      type: object
      properties:
        flags:
          type: array
          items:
            type: string
          description: IMAP flags to set on the message
        flags_add:
          type: array
          items:
            type: string
          description: IMAP flags to add to the message. Its other flags are kept, so changes another client made in the meantime are not undone. Takes precedence over flags.
          example:
          - \Seen
        flags_remove:
          type: array
          items:
            type: string
          description: IMAP flags to remove from the message. A keyword removed here is removed from its labels as well. Its other flags are kept. Takes precedence over flags.
          example:
          - \Seen
        labels:
          oneOf:
          - type: string
          - type: array
            items:
              type: string
          description: User-defined labels to set on the message. Can be a single label string or an array of labels. Labels must start with a letter, digit, backslash, or dollar sign, and can contain word characters, dots, and hyphens. Maximum of 10 labels per message. Labels are case-insensitive and will be stored in lowercase. Keywords mail clients use to track the state of a message, such as $Forwarded or $Junk, are kept unless removed with labels_remove.
          example:
          - work
          - important
        labels_add:
          type: array
          items:
            type: string
          description: Labels to add to the message. Its other labels are kept. Takes precedence over labels.
          example:
          - work
        labels_remove:
          type: array
          items:
            type: string
          description: Labels to remove from the message, for IMAP clients as well (they see labels as keywords). Its other labels are kept. Takes precedence over labels.
          example:
          - work
        folder:
          type: string
          description: Move message to this folder
  responses:
    NotFound:
      description: Not Found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InternalServerError:
      description: Internal Server Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    BadRequest:
      description: Bad Request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  parameters:
    page:
      name: page
      in: query
      description: Page of results to return. If not specified, value will be 1. Must be a number greater than or equal to 1.
      schema:
        type: integer
        minimum: 1
        default: 1
    messageId:
      name: id
      in: path
      required: true
      description: Message ID
      schema:
        type: string
    limit:
      name: limit
      in: query
      description: Number of results to return per page. Defaults to 25 if not specified. Must be a number greater than or equal to 1, and less than or equal to 100.
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 25
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: basic
      description: '

        Use your API Key as the **username** for Basic Authentication. Leave the password field empty.


        **Example:**

        If your API Key is `YOUR_API_KEY`, the Base64 encoded value for the `Authorization` header would be `echo -n "YOUR_API_KEY:" | base64`.


        ```http

        Authorization: Basic WU9VUl9BUElfS0VZOg==

        ```

        '
    AliasAuth:
      type: http
      scheme: basic
      description: '

        Use the generated **alias username and password** for Basic Authentication. This applies to endpoints under:

        *   Alias Contacts (CardDAV)

        *   Alias Calendars (CalDAV)

        *   Alias Messages (IMAP/POP3)

        *   Alias Folders (IMAP/POP3)

        *   Alias Sieve Scripts


        **Example:**

        If the alias username is `alias@domain.com` and password is `GENERATED_PASSWORD`, the Base64 encoded value would be `echo -n "alias@domain.com:GENERATED_PASSWORD" | base64`.


        ```http

        Authorization: Basic YWxpYXNAZG9tYWluLmNvbTpHRU5FUkFURURfUEFTU1dPUkQ=

        ```

        '