Notix
Use cases

Invoice emails with the PDF attached, within the limits.

An invoice email is a template, a PDF and a due date. Your app renders the PDF; the transactional email API carries it as a base64 attachment, within limits that are stated up front, sends it now or on the issue date, and reports delivery by webhook. When the file is too big to attach, the same call sends a link instead.

The flow

Render, attach or link, send.

Three steps and one column on your invoice table. The limits decide the second step, and the code checks them before the request leaves.

  1. Render the PDF.

    In your app, with your numbering and your accounting rules. Keep the file in your storage; you will want it for the customer portal and for reminders. Notix does not generate documents.

  2. Attach it, or link to it.

    Under 7 MB, attach: an object with filename and content as base64 in the attachments array. Over that, leave attachments out and put a download link in the template. Ten files and 10 MB per email, once decoded.

  3. Send with a key, now or later.

    POST /v1/emails with Idempotency-Key: invoice-{id}-send so a retry never sends twice, and scheduledAt when the invoice should go out on its issue date. Store the emailId on the invoice.

Code

Send the invoice.

curl, or the TypeScript and Python SDKs. The SDK samples check the file size and fall back to a link, and show the optional scheduledAt.

curl
# Your app renders the PDF. Notix carries it. The attachment is base64
# in the request body, and the idempotency key names the invoice so a
# retry cannot send it twice.
PDF_B64=$(base64 < invoice-2026-0912.pdf | tr -d '\n')

curl -X POST https://app.usenotix.dev/api/v1/emails \
  -H "Authorization: Bearer $NOTIX_API_KEY" \
  -H "Idempotency-Key: invoice-2026-0912-send" \
  -H "Content-Type: application/json" \
  -d "{
    \"from\": \"Acme Billing <billing@acme.com>\",
    \"to\": \"accounts@example.com\",
    \"replyTo\": \"billing@acme.com\",
    \"subject\": \"Invoice 2026-0912 from Acme, due 26 September\",
    \"templateId\": \"tpl_invoice\",
    \"variables\": {
      \"invoiceNumber\": \"2026-0912\",
      \"amountDue\": \"NGN 412,500\",
      \"dueDate\": \"26 September 2026\",
      \"payUrl\": \"https://acme.com/pay/2026-0912\"
    },
    \"attachments\": [
      { \"filename\": \"invoice-2026-0912.pdf\", \"content\": \"$PDF_B64\" }
    ]
  }"

# 200 { "emailId": "eml_abc123" }
# Too big: 400 with the field and the limit, e.g.
# { "path": ["attachments", 0, "content"], "message": "Attachment content must be at most 7 MB once decoded." }
Limits

What an attachment may be.

Every figure is the API’s documented limit, measured after base64 decoding. A request over any of them is refused before anything is stored, with the field and the limit named.

LimitValueNotes
Files per email10attachments is an array of up to ten objects.
Filename255 charactersattachments[].filename. Use the invoice number: invoice-2026-0912.pdf.
Size per file7 MB, once decodedattachments[].content is base64; a 7 MB PDF is about 9.4 MB in the request body.
Attachments per email10 MB, once decodedThe total across all files. 10 MB of attachments encodes to about 14 MB of body.
Request body20 MBApplied at the edge. A larger request answers 413 with no JSON body.
Assembled message40 MBChecked again once the message is built. Over that, the email is marked FAILED with a message that says so.
Batch of emails40 MB of attachments across the batch, once decodedUp to 100 invoices in one call to /v1/emails/batch, each with its own file.

The full request schema, the error format and the batch endpoint are in the docs; scheduling, moving and cancelling a send are on the batch and scheduled sends page.

Example

What the customer receives.

Number, amount and due date in the subject, one way to pay in the body, and the file attached or linked.

Attached

Subject: Invoice 2026-0912 from Acme, due 26 September

Invoice 2026-0912 for NGN 412,500 is attached. It is due on 26 September 2026. Pay online, or reply to this email with any question about it.

Attachment: invoice-2026-0912.pdf

Linked

Subject: Invoice 2026-0912 from Acme, due 26 September

Invoice 2026-0912 for NGN 412,500 is ready. Download the invoice (PDF, 11 MB). It is due on 26 September 2026. Pay online, or reply to this email with any question about it.

The same template, with downloadUrl set and no attachment.

Design notes

Six habits for invoices that get paid.

Render the PDF in your app.

Notix sends what you give it and does not generate documents. Use your own renderer, keep the PDF in your storage, and attach the bytes as base64. The invoice number is the filename.

Attach when small, link when large.

A one-page invoice is well under 7 MB. A statement with scans is not. Check the size before the send: attach under the limit, otherwise send a link to the file in your storage and say so in the email.

One key per invoice and purpose.

invoice-{id}-send for the first send, invoice-{id}-reminder-1 for the first reminder. A retry of the same send returns the original id; a corrected invoice is a new send with a new key and a new number.

Schedule on the issue date.

Pass scheduledAt in ISO 8601 with an offset and the email waits in the queue until then, with its status SCHEDULED. Update or cancel it before it goes out if the invoice changes.

Put the amount and the due date in the subject.

Accounts teams triage by subject line. Invoice number, sender, amount or due date in the subject means the email is found in a search six months later.

Track delivery, not opens.

Open tracking on invoices produces noise from security scanners. Listen for email.delivered and email.bounced by webhook, and treat a permanent bounce as a wrong billing address to fix on the customer record.

FAQ

Questions, answered.

How do I send an invoice email with a PDF through an API?
One POST to /api/v1/emails with the invoice values as template variables and the PDF as an attachment: an object with filename and content, where content is the file encoded as base64. Up to ten files, 7 MB each and 10 MB in total once decoded. Add an Idempotency-Key naming the invoice so a retried request cannot send it twice, and store the emailId on the invoice. Your app renders the PDF; Notix carries it.
What is the maximum attachment size?
7 MB per file and 10 MB across all attachments on one email, measured after base64 decoding. Ten files at most. The whole request body is capped at 20 MB at the edge, and the assembled message at 40 MB. A request over a limit answers 400 with the field and the limit named; a body over 20 MB answers 413 with no JSON. For a batch call, attachments across the batch are capped at 40 MB decoded.
The PDF is bigger than 7 MB. What do I do?
Send a link instead of a file. Keep the PDF in your own storage, put a signed or authenticated download link in the email, and leave attachments out. The sample code checks the size and switches automatically, and the template shows the download link only when it is set. Compressing scanned pages before rendering usually brings a statement under the limit anyway.
Does Notix generate the invoice PDF?
No. Notix is the sending layer: it accepts the file you attach, delivers the email and reports what happened. Rendering the invoice, numbering it and storing it stay in your application, where the accounting rules live. Any PDF library that produces bytes works; the attachment field takes base64 of those bytes.
Can I send the invoice on a future date?
Yes. Pass scheduledAt as an ISO 8601 timestamp with an offset and the email waits in the queue with status SCHEDULED until then. It can be moved with PATCH /v1/emails/{id} or cancelled with POST /v1/emails/{id}/cancel before it goes out. Suppression is checked again at send time, so an address that bounced in the meantime is not sent to.
How do I know the invoice was received?
Add a webhook endpoint for email.delivered and email.bounced. Each event carries the emailId from the send response, so your handler finds the invoice and records delivered, or flags a wrong billing address on a permanent bounce. The email log in the dashboard shows the same timeline. Open tracking is a poor signal for invoices because security scanners open them; use delivery events instead.

Send the first invoice in an afternoon.

One call with the PDF attached, limits you can see before you build, and the free plan's 5,000 emails a month to test with. No card.