HelipodDocs

Inbox (receiving)

Receive email on your verified domains, manage mailboxes and aliases, and read and reply to received mail.

Helipod Email can also receive mail for a verified domain (or one of its subdomains). Received messages are stored in your project, can be forwarded, trigger an email.received webhook, and can be read in webmail or through this API.

Receiving needs a paid plan that includes mailboxes (402 PLAN_REQUIRED otherwise). All endpoints on this page accept an email API key (or a Helipod API key with the Email API enabled) and act on the key's project.

Set up receiving

Check the receiving host

GET/domains/{id}/inbound/check
Look up the MX records of the host that will receive mail.
QueryTypeNotes
hoststringThe domain itself or a subdomain of it, for example mail.example.com. Defaults to the domain. Must not be the domain's MAIL FROM (bounce) host.
curl "https://mail.helipod.io/api/email/domains/3f2a9c4e-1b7d-4e0a-9c55-2d8f6b1a7e10/inbound/check?host=mail.example.com" \
  -H "Authorization: Bearer your_email_api_key"
{ "success": true, "data": { "host": "mail.example.com", "existingMx": ["mx1.current-provider.example"] } }
  • existingMx lists other mail servers that currently receive mail for the host. If it is not empty, enabling receiving on this host moves that mail to Helipod. Use a dedicated subdomain if you want to keep your current mailbox provider for the main domain.
  • After you publish the receiving MX record, the domain's inboundMxValid (see step 3) tells you when it is live.

Enable receiving

POST/domains/{id}/inbound
Turn receiving on or off for a verified domain.

Prop

Type

curl -X POST https://mail.helipod.io/api/email/domains/3f2a9c4e-1b7d-4e0a-9c55-2d8f6b1a7e10/inbound \
  -H "Authorization: Bearer your_email_api_key" \
  -H "Content-Type: application/json" \
  -d '{"enabled":true,"host":"mail.example.com"}'

Returns the domain object. Its dnsRecords now include the receiving MX record. Errors: 409 DOMAIN_NOT_VERIFIED, 400 INVALID_HOST, 409 INBOUND_HOST_TAKEN (the host already receives mail in another project), 402 PLAN_REQUIRED.

Publish the MX record and verify

Publish the receiving MX record from dnsRecords at your DNS provider, then call POST /domains/{id}/verify. inboundMxValid on the domain turns true when the record is live.

Create a mailbox

Create at least one address. Mail to an address that does not exist, or is inactive, is dropped.

Usage and limits

GET/inbound/stats
Inbox usage against your plan.
curl https://mail.helipod.io/api/email/inbound/stats \
  -H "Authorization: Bearer your_email_api_key"
{
  "success": true,
  "data": {
    "available": true,
    "unread": 4,
    "monthCount": 128,
    "mailboxes": 2,
    "maxMailboxes": 5,
    "includedMailboxes": 5,
    "extraMailboxes": 0,
    "aliases": 3,
    "maxAliasesPerMailbox": 10,
    "storageUsedBytes": 73400320,
    "storageLimitBytes": 5368709120,
    "receivedBytes": 52428800,
    "receivedLimitBytes": 10737418240,
    "receivedCycleStart": "2026-10-01",
    "includedStorageGb": 5,
    "extraStorageGb": 0,
    "allowForwarding": true,
    "receivingDomains": 1,
    "spamTrashDays": 30
  }
}

The response also carries mailboxUnitPrice and storageGbUnitPrice: your plan's monthly add-on prices for one extra mailbox and one extra GB of storage, as decimal strings in Rupiah. available is false when the plan does not include receiving. Spam and Trash empty themselves after spamTrashDays days. Other received mail is kept until you delete it. If the project no longer has a plan that includes receiving, its received mail is deleted 30 days after the last subscription ended.

Addresses

There are two kinds of address:

  • mailbox: a real inbox on a receiving domain. Can forward, notify, and sign in to webmail once it has a password. Limited by your plan's mailboxes (402 MAILBOX_LIMIT).
  • alias: another address on the same domain that delivers into a mailbox. Limited per mailbox (402 ALIAS_LIMIT). There are no catch-all addresses.

Plus-addressing works: mail to [email protected] is delivered to [email protected].

Address object

Prop

Type

List addresses

GET/inbound/addresses
Mailboxes, each followed by its aliases.
curl https://mail.helipod.io/api/email/inbound/addresses \
  -H "Authorization: Bearer your_email_api_key"

Create an address

POST/inbound/addresses
Create a mailbox, or an alias of a mailbox.

Prop

Type

curl -X POST https://mail.helipod.io/api/email/inbound/addresses \
  -H "Authorization: Bearer your_email_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "mailbox",
    "domainId": "3f2a9c4e-1b7d-4e0a-9c55-2d8f6b1a7e10",
    "localPart": "support",
    "displayName": "Acme Support",
    "forwardTo": ["[email protected]"]
  }'

Response 201: the address object. A new mailbox receives a short welcome message once its domain's MX record is live.

Errors: 404 DOMAIN_NOT_FOUND, 404 MAILBOX_NOT_FOUND, 409 DOMAIN_NOT_RECEIVING, 400 INVALID_ADDRESS, 409 ADDRESS_EXISTS, 402 MAILBOX_LIMIT, 402 ALIAS_LIMIT, 402 FORWARDING_NOT_ALLOWED.

Update an address

PATCH/inbound/addresses/{id}
Change a mailbox's settings, or turn an address on or off.

Prop

Type

curl -X PATCH https://mail.helipod.io/api/email/inbound/addresses/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d \
  -H "Authorization: Bearer your_email_api_key" \
  -H "Content-Type: application/json" \
  -d '{"forwardTo":[],"notify":false}'

Returns the address object. Setting mailbox-only fields on an alias returns 400 ALIAS_SETTINGS.

Set a webmail password

POST/inbound/addresses/{id}/password
Enable webmail sign-in for a mailbox, or disable it with null.

This route is for the dashboard: an API key gets 403 KEY_NOT_ALLOWED, because a key holder who could set the password could read the mailbox.

Prop

Type

curl -X POST https://mail.helipod.io/api/email/inbound/addresses/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d/password \
  -H "Authorization: Bearer your_email_api_key" \
  -H "Content-Type: application/json" \
  -d '{"password":"correct-horse-battery-staple"}'

Returns the address object with webmail: true. Any existing webmail sessions of the mailbox are signed out. Errors: 400 WEAK_PASSWORD, 400 ALIAS_SETTINGS (aliases cannot sign in).

Delete an address

DELETE/inbound/addresses/{id}
Delete an address. Deleting a mailbox also deletes its aliases.
curl -X DELETE https://mail.helipod.io/api/email/inbound/addresses/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d \
  -H "Authorization: Bearer your_email_api_key"
{ "success": true, "data": { "deleted": true } }

Messages already received are kept.

Messages

Message object

The list returns these fields:

Prop

Type

GET /inbound/messages/{id} adds cc, bcc, replyTo, textBody, htmlBody, attachments (index, filename, contentType, size, and cid/inline for inline images), messageIdHeader, inReplyTo, verdicts (spf, dkim, dmarc, spam, virus) and sizeBytes.

List messages

GET/inbound/messages
Received messages, newest first.
QueryTypeNotes
folderinbox | spam | archive | trashDefault inbox.
addressIdstring (uuid)Only messages to this address.
unread1 | trueOnly unread messages.
starred1 | trueOnly starred messages.
searchstringSubject, sender, snippet or recipients contain this text. Up to 200 characters.
limitnumber1 to 200, default 50.
cursorstringnextCursor from the previous page.
curl "https://mail.helipod.io/api/email/inbound/messages?folder=inbox&unread=1" \
  -H "Authorization: Bearer your_email_api_key"
{
  "success": true,
  "data": {
    "data": [
      {
        "id": "4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b",
        "addressId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
        "recipient": "[email protected]",
        "deliveredTo": ["[email protected]"],
        "to": ["[email protected]"],
        "from": "[email protected]",
        "fromName": "Ana Putri",
        "subject": "Question about my order",
        "snippet": "Hi, I ordered on Monday and ...",
        "receivedAt": "2026-10-16T10:02:11.000Z",
        "isRead": false,
        "isStarred": false,
        "folder": "inbox",
        "hasAttachments": true,
        "spamVerdict": "PASS",
        "virusVerdict": "PASS"
      }
    ],
    "nextCursor": null,
    "total": 1
  }
}

total is the number of messages matching the filters (without the cursor). Errors: 400 INVALID_CURSOR.

Get a message

GET/inbound/messages/{id}
Full message. Reading it does not mark it as read.
curl https://mail.helipod.io/api/email/inbound/messages/4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b \
  -H "Authorization: Bearer your_email_api_key"

Returns 404 MESSAGE_NOT_FOUND for an unknown id.

Update a message

PATCH/inbound/messages/{id}
Mark read or starred, or move to a folder.

Prop

Type

curl -X PATCH https://mail.helipod.io/api/email/inbound/messages/4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b \
  -H "Authorization: Bearer your_email_api_key" \
  -H "Content-Type: application/json" \
  -d '{"isRead":true,"folder":"archive"}'

Returns the message in list form. Errors: 400 NOTHING_TO_UPDATE, 400 INVALID_FOLDER.

Bulk update

POST/inbound/messages/bulk
Mark, move or delete up to 500 messages.

Prop

Type

curl -X POST https://mail.helipod.io/api/email/inbound/messages/bulk \
  -H "Authorization: Bearer your_email_api_key" \
  -H "Content-Type: application/json" \
  -d '{"ids":["4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b"],"action":"archive"}'
{ "success": true, "data": { "updated": 1 } }

Ids that do not belong to the project are ignored.

Delete a message

DELETE/inbound/messages/{id}
Delete a message permanently.
curl -X DELETE https://mail.helipod.io/api/email/inbound/messages/4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b \
  -H "Authorization: Bearer your_email_api_key"
{ "success": true, "data": { "deleted": true } }

Download an attachment

GET/inbound/messages/{id}/attachments/{index}
A short-lived download URL for one attachment.

index is the attachment's index from the message detail.

curl https://mail.helipod.io/api/email/inbound/messages/4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b/attachments/0 \
  -H "Authorization: Bearer your_email_api_key"
{ "success": true, "data": { "url": "https://...", "expiresIn": 60 } }

expiresIn is in seconds. Download the file right away and request a new URL if it expires. Errors: 404 ATTACHMENT_NOT_FOUND.

Download the original message

GET/inbound/messages/{id}/raw
A short-lived download URL for the original .eml file.
curl https://mail.helipod.io/api/email/inbound/messages/4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b/raw \
  -H "Authorization: Bearer your_email_api_key"

Same response shape as an attachment. Returns 404 RAW_NOT_AVAILABLE when the original was not kept (for example a message flagged as containing a virus).

Reply to a message

POST/inbound/messages/{id}/replycharges your wallet
Send a threaded reply from the receiving address.

Prop

Type

curl -X POST https://mail.helipod.io/api/email/inbound/messages/4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b/reply \
  -H "Authorization: Bearer your_email_api_key" \
  -H "Content-Type: application/json" \
  -d '{"text":"Hi Ana, your order ships tomorrow.\n\nAcme Support"}'
{ "success": true, "data": { "emailId": "c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f", "jobId": "eml_c3d4e5f6a7b84c9d8e0f" } }

Response status is 202. The reply goes to the original Reply-To (or sender), with the subject prefixed Re: and threading headers set. It goes through the normal send path: it counts toward your quota, appears in the email log under emailId, and can fail with the same errors. The original is not quoted; include it in your body if you want it. Errors: 400 BODY_REQUIRED.

On this page