Email

Send one email

Sends one email from an address on a verified sending domain of this project, like Resend: to is one address or a list, with optional cc and bcc (at most 50 recipients together). Everyone in to and cc sees the others; use bcc or POST /emails/batch when people must not see each other. Every recipient must appear in the project (a form submission, a document, a chat conversation, a user of one of your apps) or be confirmed by the owner. category other (the default) adds an unsubscribe link and header plus the project's postal address (from PUT /project/company, required by the US CAN-SPAM Act; without it the email is refused with company_details_missing) and goes to exactly one recipient; several recipients need category transactional (a reply to something they all did). attachments: at most 10 files, 10 MB together, each with a filename and one of content (base64), media_id (a file from Media) or path (an https address on one of this project's sites). Allowed: PDF, PNG, JPG, GIF, WebP, and ICS, TXT or CSV as UTF-8 text; the type is checked on the file's first bytes. Keep the request under about 4 MB; use media_id or path for larger files. Every email passes a content check (no phishing, no scripts or forms, no links that hide where they go). Limits count every recipient: a daily limit per project, 200 recipients and 20 calls per minute, and a cap on new recipients a day that only appear in documents your app wrote (25 to start, growing to 100 and 500 as emails are delivered without bounces or complaints; see mail.new_recipients in GET /emails). Each recipient also counts as one email for the bundle. Sending pauses automatically when bounces exceed 5% or spam complaints exceed 0.1% over the last 200 emails. With a test key nothing is sent: after all the same checks, the email gets status simulated. An Idempotency-Key (header or idempotency_key) returns the same email instead of a second one. template_id with data sends a template (POST /email-templates) instead of subject, html and text. send_at sends it later (at most 30 days ahead): the answer is then a scheduled email (202), which POST /scheduled-emails/{id}/cancel stops.

post/emails

Request

  • Base URL: https://api.hypamoon.com/api/v1
  • URL: https://api.hypamoon.com/api/v1/emails
  • Auth: one of:
    • HTTP bearer
    • OAuth 2 (authorization code, authorization URL https://app.hypamoon.com/oauth/authorize, token URL https://api.hypamoon.com/oauth/token, scopes: messages:write)

Headers

Idempotency-Keystring

Optional. The same key returns the same email instead of sending it again.

Request body

fromstring required

The sender: an address on a verified sending domain of this project, optionally with a name, like "Acme Plumbing hello@acme.com".

ccstring[]

Optional. Copy recipients; they see the to and cc addresses. The same rules as to.

bccstring[]

Optional. Hidden recipients; nobody sees them. The same rules as to.

subjectstring

The subject line. Required without template_id; with template_id it comes from the template.

textstring

The plain text body. Send text, html or both.

htmlstring

The HTML body. No scripts, no forms; links must show where they go.

reply_tostring

Optional. Where replies go, like the user's own mailbox.

category'transactional' | 'other'

transactional: a reply to something the recipients did (an order, a booking, a form they sent). other (default): anything else; it gets an unsubscribe link with the project's postal address (needs a business address in the company details) and a List-Unsubscribe header, is not sent to people who unsubscribed, and goes to exactly one recipient (use a batch for more people).

in_reply_tostring uuid

The id of the form submission (a document from a public form) or the chat conversation this email answers. Required when the recipient appears in the project only through a form or a chat; the address must be in that submission or conversation.

check_recipientsboolean

Optional, default true: before the first email to an address, check that its domain exists and accepts email, and refuse likely typos (like gmial.com) and, for category other, throwaway addresses. false skips those checks; an address that bounced before is always refused.

idempotency_keystring

Optional. The same key returns the same email instead of sending a second one (also as the Idempotency-Key header).

template_idstring uuid

Optional. A template (create_email_template): the subject, html and text come from it, filled with data. Leave out subject, html and text.

dataobject

With template_id: the values for its variables, like { "name": "Sam" }.

send_atstring

Optional. Send later, like 2026-11-02T09:00:00Z, at most 30 days ahead: the answer is a scheduled email (202) that cancel_scheduled_email can stop. All checks except the form run when it is sent.

Response

The same Idempotency-Key as before: the original email, and nothing is sent again.

idstring uuid required

The id of the email. sendEmail and sendEmailBatch in an app return it; getEmail(id) reads it back.

app_idstring uuid nullable required

The app that sent it with env.HYPAMOON.sendEmail; null when it was sent with the API, by an agent or from the portal.

fromstring required
tostring required

The first address in to. All recipients are in recipients.

recipient_countinteger required

to, cc and bcc together; each counts toward the limits and the bundle.

reply_tostring nullable required
subjectstring required
category'transactional' | 'other' required
status'queued' | 'sent' | 'delivered' | 'bounced' | 'complained' | 'failed' | 'simulated' required

queued, sent (accepted for delivery), delivered, bounced, complained (marked as spam), failed, or simulated (test mode).

recipient_source'confirmed' | 'member' | 'form' | 'document' | 'conversation' | 'app_user' | 'buyer' | 'pass_holder' | 'null' nullable required

Where the recipient appears in the project.

testboolean required
errorstring nullable required
reasonstring nullable required

Why the email bounced, was marked as spam, is delayed or was not sent, in plain words. null otherwise.

created_atstring required
sent_atstring nullable required
delivered_atstring nullable required
bounced_atstring nullable required
complained_atstring nullable required
sender'hypamoon_fallback'

Only when the project has no verified sending domain of its own: the email went from Hypamoon's address ("<app or project> via Hypamoon"), in a neutral layout without the project's images or design. Tell the user so.

next_stepstring

With sender hypamoon_fallback: how to send from the project's own address with its own design.

Changes

No recorded changes to this operation across all 1 revision of this API.