Inboxy Mail API

Compose and send from your aliases.

GitHub OpenAPI

Operations 3

POST /v1/mail/send Send a composed message from one of your aliases #
POST /v1/mail/import Import a historic email onto one of your aliases #
POST /v1/mail/invite Invite a friend to inboxy #

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/inboxy-net:inboxy-net-mail-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

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

inboxy-net-mail-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: inboxy Mail API
  version: 0.3.0
  summary: Read + manage your inboxy.net inbox programmatically.
  description: 'REST surface over the inboxy alias inbox. Mint aliases, list/search/read

    messages, fetch attachments, manage your API keys, and emit user-initiated

    mail under one of your aliases.


    Mail-emitting paths (`POST /v1/messages/{id}/reply`, `POST /v1/mail/send`,

    `POST /v1/mail/invite`) are recipient-locked and alias-locked server-side:

    the `From:` is always one of the caller''s `@inboxy.net` aliases, the

    recipient is validated against per-user caps and the abuse rules in

    `packages/reply`, and every external message carries the mandatory

    inboxy attribution footer. There is no arbitrary-`From:` send path.


    All endpoints require a bearer API key created from the inboxy.net web UI

    at `/account/keys` (mint is gated by step-up and lives only on the web — there

    is no API-channel mint). Pass it as `Authorization: Bearer ik_…`.


    The signed-token attachment download URLs (`/v1/attachments/{token}/download`,

    `/v1/messages/raw/{token}/download`) are public-by-token — they intentionally

    bypass bearer auth and are not listed here. Obtain them via the JSON

    endpoints below.'
  contact:
    name: inboxy
    url: https://inboxy.net
  license:
    name: Proprietary
servers:
- url: https://api.inboxy.net
  description: Production
security:
- bearerAuth: []
tags:
- name: Mail
  description: Compose and send from your aliases.
paths:
  /v1/mail/send:
    post:
      tags:
      - Mail
      summary: Send a composed message from one of your aliases
      description: REST mirror of the MCP `mail_send` tool. Requires `send` scope. The `From:` is locked to one of the caller's active `@inboxy.net` aliases (forced to the bound alias on address-scoped keys). Recipients are classified internal vs external; external sends enqueue onto `outbound-send` and carry the inboxy attribution footer. Plan-tier daily caps + per-user rate limits apply.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MailSendRequest'
      responses:
        '202':
          description: Accepted — internal delivery completed, external queued.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MailSendResult'
        '400':
          description: Validation failure (`from_missing`, `from_not_owned`, `from_retired`, `to_missing`, `subject_missing`, `body_missing`, `body_too_long`, …).
        '403':
          description: '`key_scope_mismatch` (address-scoped key called with a different `from_local_part`) or recipient blocked by abuse rules.'
        '429':
          description: '`quota_exhausted` — body includes `code` + `remaining`. The mail-send quota refills daily.'
      operationId: postV1MailSend
      x-operation-id-source: derived
  /v1/mail/import:
    post:
      tags:
      - Mail
      summary: Import a historic email onto one of your aliases
      description: 'REST mirror of the MCP `mail_import` tool. Requires `manage` scope. Push one raw RFC 5322 message (an `.eml`) that never arrived at inboxy — old order mail from another mailbox, say — and it is stored, classified and embedded for `mail_search` exactly like inbound mail. It is an archive write: never forwarded, never digested, stored as read, and its retention clock starts at import rather than at its own `Date:`. Mail whose `From:` is your own sign-in address is accepted and flagged `sent_by_user`. Dedup is per user on `Message-ID:`. Capped per UTC calendar month (500 free / 5000 paid); 10 MiB per message.'
      parameters:
      - name: address_id
        in: query
        required: false
        schema:
          type: string
          format: uuid
        description: Row id of one of your active addresses; the message is filed under it. Give this or `address`. Address-scoped keys must name their bound address.
      - name: address
        in: query
        required: false
        schema:
          type: string
        description: The alias by name — `<local>@inboxy.net` or just the local-part, case-insensitive. Alternative to `address_id`; if both are given they must agree.
      requestBody:
        required: true
        description: The raw message bytes, unencoded.
        content:
          message/rfc822:
            schema:
              type: string
              format: binary
          application/octet-stream:
            schema:
              type: string
              format: binary
      responses:
        '200':
          description: 'Already stored (`duplicate: true`); nothing changed.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MailImportResult'
        '201':
          description: Stored and queued for classification + embedding.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MailImportResult'
        '400':
          description: '`bad_request` (neither `address_id` nor `address`, an `address` not on inboxy.net, or the two disagreeing) or `unparseable` (no `From:` address).'
        '403':
          description: Address not yours or retired, or `key_scope_mismatch` on an address-scoped key.
        '413':
          description: '`too_large` — over 10 MiB.'
        '429':
          description: '`import_quota_exhausted` — body includes `period_resets_at`.'
      operationId: postV1MailImport
      x-operation-id-source: derived
  /v1/mail/invite:
    post:
      tags:
      - Mail
      summary: Invite a friend to inboxy
      description: REST mirror of the MCP `mail_invite` tool. Requires `send` scope. One magic-link email is sent from `invites@mail.inboxy.net`. Capped at 10 per rolling 30 days per inviter. Refuses self-invites, existing-user invites, and reserved local-parts.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MailInviteRequest'
      responses:
        '200':
          description: Invite queued; magic-link valid 30 days.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MailInviteResult'
        '400':
          description: Validation failure (`to_missing`, `to_unparseable`, `recipient_reserved`, `self_invite`, `note_too_long`, `note_has_link`).
        '403':
          description: '`recipient_already_user` — the invitee already has an inboxy account.'
        '429':
          description: '`invite_cap_reached` — body includes `remaining: 0` + `resets_at` (Unix seconds).'
      operationId: postV1MailInvite
      x-operation-id-source: derived
components:
  schemas:
    MailInviteResult:
      type: object
      required:
      - invite_id
      - expires_at
      - invites_remaining
      properties:
        invite_id:
          type: string
          description: Opaque id; surfaces in `audit_log`.
        expires_at:
          type: integer
          description: Unix seconds when the invite token expires (30 days from issue).
        invites_remaining:
          type: integer
          description: Remaining invites in the caller's rolling 30-day window.
    MailSendResult:
      type: object
      required:
      - ok
      - delivery
      - from
      - to
      - subject
      - idempotency_key
      properties:
        ok:
          type: boolean
          enum:
          - true
        delivery:
          type: string
          enum:
          - internal
          - external
          description: '`internal` = recipient is another inboxy user; delivered directly. `external` = enqueued onto `outbound-send` for the sender worker.'
        message_id:
          type: string
          format: uuid
          description: Present on internal delivery only — the recipient's new `messages.id`.
        from:
          type: string
          format: email
        to:
          type: string
          format: email
        subject:
          type: string
        idempotency_key:
          type: string
    MailSendRequest:
      type: object
      required:
      - from_local_part
      - to
      - subject
      description: 'Compose a new message from one of the caller''s @inboxy.net aliases. The recipient is classified server-side: internal recipients (another `@inboxy.net` user) bypass external SMTP and land in the recipient''s inbox; external recipients enqueue via the sender worker and carry the mandatory inboxy attribution footer.'
      properties:
        from_local_part:
          type: string
          description: Local-part of the alias to send from. Must be one of the caller's active aliases. When the API key is address-scoped this is forced to the bound alias and `key_scope_mismatch` is returned on conflict.
        to:
          type: string
          description: RFC 5322 recipient address. Mailbox-syntax validated server-side.
        subject:
          type: string
          maxLength: 200
          description: Trimmed and truncated at 200 chars.
        text:
          type: string
          maxLength: 8000
          description: Plain-text body. Required if `html` is absent.
        html:
          type: string
          maxLength: 64000
          description: Optional HTML body.
        in_reply_to:
          type: string
          description: Optional `Message-Id` to thread against. Sanitized server-side before being written to headers.
    MailInviteRequest:
      type: object
      required:
      - to
      description: Invite a friend to inboxy. The recipient receives a single magic-link email from `invites@mail.inboxy.net` — no further mail until they accept. Capped at 10 invites per rolling 30 days per inviter. Self-invites, invites to existing users, and invites to reserved local-parts are refused.
      properties:
        to:
          type: string
          format: email
          description: Invitee's personal email.
        personal_note:
          type: string
          maxLength: 500
          description: Optional ≤500-char note included in the invite body, labelled as written by the inviter. Links, web addresses and email addresses are refused (`note_has_link`).
    MailImportResult:
      type: object
      required:
      - message_id
      - message_id_rfc5322
      - duplicate
      - sent_by_user
      properties:
        message_id:
          type: string
          format: uuid
          description: The `messages.id` — the newly stored row on a 201, or the already-existing row on a duplicate, so it can be fetched either way.
        message_id_rfc5322:
          type: string
          description: The message's `Message-ID:`, or `<inboxy-import-{sha256}@inboxy.net>` synthesised from the bytes when the header is absent. Dedup key per user.
        duplicate:
          type: boolean
          description: '`true` when this Message-ID was already stored for you; nothing was written and the quota was not spent.'
        sent_by_user:
          type: boolean
          description: '`true` when the `From:` is your own sign-in address — mail you sent. Stored for context; `mail_reply` refuses it.'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: ik_…
      description: Static API key. Three scopes — `read` (everything except mutations), `manage` (mutations other than sending) and `send` (`/v1/mail/send`, replies, invites). Mint at https://inboxy.net/account/keys (the web UI gates mint with step-up; there is no API-channel mint).