ForHosting KIT · Notifications & Flows

Email a file as attachment

POST /notify/email-attachment takes a file you've just generated — an invoice, a receipt, a signed contract — and delivers it as an attachment on a message that goes out from your own domain. It's built for the exact moment a document exists only because your system produced it seconds ago and now has to reach someone's inbox.

● StablePer request + per email$0.002
Use it from WebAPIEmailApp soonTelegram soon

The gap between generating a file and delivering it

Plenty of systems can render a PDF invoice or export a CSV report in milliseconds; far fewer make it trivial to then get that file into an inbox reliably. This endpoint closes that specific gap: you already did the hard part of producing the document, and this call handles the last step — packaging it as an attachment and delivering it — without you having to manage SMTP connections or MIME encoding by hand.

What the request looks like

Alongside the usual recipient, subject and body, you include the file content and its name; the API encodes it correctly for email transport, queues the send and returns a task_id immediately. The actual delivery happens moments later on our global edge, and the outcome — accepted, delivered, bounced, failed — comes back through a signed webhook or a signed link valid for 24 hours, so your system knows for certain the invoice reached its destination and not just that you asked us to send it.

Why attachments are still the safest default

Sending a document as a link instead of an attachment feels modern, but it introduces a dependency: the link has to stay valid, the recipient has to trust clicking it, and some corporate filters flag unfamiliar links more aggressively than a plain attachment. For anything a person needs to keep — a receipt for their records, a signed agreement — an attachment that lands directly in the message is still the format people expect and archive without a second thought.

Where size and format expectations come in

Attachments work best for the documents email was designed to carry: PDFs, images, small spreadsheets — the kind of file a person opens once and files away. Very large binaries strain every mail provider's limits regardless of the sending API, so the practical pattern for bulky exports is generating them as a file and referencing them by link, while this endpoint stays focused on the invoice-sized attachment it does well.

Slotting into a document pipeline

Because the call is asynchronous and retried automatically up to three times before a clear error is returned, it drops cleanly into a pipeline where a PDF generator produces the file and this endpoint ships it in the same request-response cycle, with no charge for a failed attempt.

Invoices after checkout

The moment your billing system renders a PDF invoice, this endpoint emails it directly to the customer from your own domain.

Signed contracts and agreements

Once a document workflow finalizes a signed PDF, it's delivered as an attachment so the signer has a permanent copy in their inbox.

Weekly report exports

An internal reporting job generates a small CSV or PDF summary and emails it to a stakeholder list without anyone opening a dashboard.

Receipts for one-off payments

A payment confirmation triggers a receipt PDF that's attached and sent the moment the transaction clears.

What file types can I attach?

The endpoint is built for the documents email attachments were meant to carry — PDFs, images, small spreadsheets and similar formats generated on the fly.

Is there a size limit on attachments?

Yes, practical limits apply as with any email attachment; very large files should be delivered as a link rather than attached directly.

How much does it cost?

$0.002 per request plus $0.0035 per email sent — the same pricing as a standard transactional email, with no extra fee for the attachment itself.

Is there a free way to test this?

There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.

How do I know the attachment was actually delivered?

The signed webhook or signed link reports the delivery event — accepted, delivered, bounced or failed — so you're not left guessing.

Can I send the same file to multiple recipients in one call?

Each call targets a single send; for multiple recipients, issue one request per recipient so delivery and retries are tracked independently.

What happens if the attachment fails to send?

The task retries automatically up to three times, and a failed task is never charged — you only get billed for a delivery attempt that actually goes out.

Why not just send a download link instead?

Links depend on staying valid and being trusted enough to click; an attachment lands directly in the message, which is still what people expect for receipts and signed documents.

Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.

POSThttps://api.kit.forhosting.com/notify/email-attachment

Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.

curl -X POST https://api.kit.forhosting.com/notify/email-attachment \
  -H "Authorization: Bearer $KIT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":"…"}'
{
  "input": "…"
}
{
  "task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
  "type": "notify.email_attachment",
  "status": "queued",
  "_links": {
    "result": "/tasks/tsk_…/result"
  }
}

The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.

Per request$0.002
Per email$0.0035

Published price — no tokens, no invented credits. A failed task is never charged.

HTTPCodeMeaning
401unauthorizedMissing or invalid API key.
402insufficient_balanceYour balance doesn't cover the task price.
404unknown_typeThat task type doesn't exist.
429rate_limitedToo many requests. Use the webhook instead of polling.

Read the full KIT documentation →