FinzBooksDevelopers

Email send

Mail a customer-facing document (invoice, estimate, credit note) with the FinzBooks PDF attached, via the org's configured AWS SES sender. One HTTP call, MIME-attached bytes, no manual SMTP plumbing.

Every send takes a list of recipients, optional cc / bcc, an optional subject + HTML body override, and a flag to attach (or skip) the generated PDF. When no subject / body is supplied, FinzBooks fills in a sensible default — “Invoice INV-2026-0042 from Acme Industries” in the subject and a short greeting body that names the customer, the document number, and the total.

Authentication & scopes

Each endpoint requires the resource's UPDATE scope — same scope that lets you approve / void the document. Read-only tokens can't email customers, because sending an email is a state-altering side-effect from a deliverability standpoint (it can be bounced, marked as spam, etc.) and is recorded in the activity log.

Common request headers

Authorization:   Bearer aibooks_pat_XXXX...
X-AIBooks-Org:   org_8f9a1c2d
Content-Type:    application/json

Request body — common to all three endpoints

FieldTypeNotes
to[]string[]One or more recipient addresses. Required.
cc[]string[]Optional carbon copies.
bcc[]string[]Optional blind copies. Hidden from the visible header.
subjectstringUp to 500 chars. Falls back to “<Doc> <number> from <Org>” when omitted.
body_htmlstringUp to 50 000 chars. Raw HTML; assume sanitised by your client. Falls back to a minimal default template.
attach_pdfboolDefault true. Set false to send a body-only email.
POST/invoices/{invoice_id}/emailEmail an invoiceAIBooks.invoices.UPDATE

Used for both initial invoice delivery and follow-up nudges. The PDF — when attached — is the same render thePDF endpoint emits, so what the recipient sees matches what your dashboard shows. Status changes do NOT happen automatically: a DRAFT invoice emailed is still DRAFT after the send. Approve it first (POST /invoices/{id}/approve) if you want the recipient to see a posted invoice.

Default subject

Invoice <number> from <org name>

Default body

Hello <customer>,

Please find the invoice <number> from <org name> attached.

Total: ₹<total>

Thank you,
<org name>

Sample request

POST /api/public/v1/invoices/inv_8c3f1a9b/email HTTP/1.1
Host: api.aibooks.in
Authorization: Bearer aibooks_pat_3p9q0v1w2x3y4z5a6b7c8d9e
X-AIBooks-Org: org_8f9a1c2d
Content-Type: application/json

{
  "to":         ["priya@acme.in", "ap@acme.in"],
  "cc":         ["sales@yourdomain.com"],
  "bcc":        ["audit-trail@yourdomain.com"],
  "subject":    "Invoice INV-2026-0042 — due 27 May",
  "body_html":  "<p>Hi Priya,</p><p>Attached is invoice <b>INV-2026-0042</b> for ₹1,18,000 (incl. 18% GST). Due on 27 May 2026.</p><p>Thanks,<br/>Acme Industries</p>",
  "attach_pdf": true
}

Sample response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code":    0,
  "message": "The invoice has been emailed.",
  "delivery": {
    "message_id":   "0102018a-4d1f-7c2b-9a0e-7f6b3c8e1d22-000000",
    "from":         "billing@acme.in",
    "to":           ["priya@acme.in", "ap@acme.in"],
    "cc":           ["sales@yourdomain.com"],
    "bcc_count":    1,
    "subject":      "Invoice INV-2026-0042 — due 27 May",
    "attached_pdf": true,
    "pdf_filename": "INV-2026-0042.pdf",
    "pdf_size":     184236,
    "sent_at":      "2026-05-12T08:32:14Z"
  }
}
POST/estimates/{estimate_id}/emailEmail an estimateAIBooks.estimates.UPDATE

Same body shape, same defaults — substitutes “Estimate” for “Invoice” in the subject. Common pattern: send a DRAFT estimate, mark it SENT, and use the activity timeline to follow up if the customer doesn't respond within the expiry window.

Sample request

POST /api/public/v1/estimates/est_9b1c3d5e/email HTTP/1.1
Host: api.aibooks.in
Authorization: Bearer aibooks_pat_3p9q0v1w2x3y4z5a6b7c8d9e
X-AIBooks-Org: org_8f9a1c2d
Content-Type: application/json

{
  "to":         ["rohit@contoso.in"],
  "subject":    "Quote EST-2026-0073 — valid till 25 May",
  "attach_pdf": true
}

Sample response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code":    0,
  "message": "The estimate has been emailed.",
  "delivery": {
    "message_id":   "0102018a-4d1f-7c2b-9a0e-7f6b3c8e1d23-000000",
    "from":         "sales@acme.in",
    "to":           ["rohit@contoso.in"],
    "cc":           [],
    "bcc_count":    0,
    "subject":      "Quote EST-2026-0073 — valid till 25 May",
    "attached_pdf": true,
    "pdf_filename": "EST-2026-0073.pdf",
    "pdf_size":     96512,
    "sent_at":      "2026-05-12T08:34:01Z"
  }
}
POST/credit_notes/{credit_note_id}/emailEmail a credit noteAIBooks.creditnotes.UPDATE

Customer-facing only — credit notes raised against bills (vendor refunds) shouldn't be emailed from this endpoint because the recipient model assumes a customer contact. Pass the customer's address explicitly in to[] if the contact's primary email isn't the right one.

Sample request

POST /api/public/v1/credit_notes/cn_7a2b4c6d/email HTTP/1.1
Host: api.aibooks.in
Authorization: Bearer aibooks_pat_3p9q0v1w2x3y4z5a6b7c8d9e
X-AIBooks-Org: org_8f9a1c2d
Content-Type: application/json

{
  "to":         ["priya@acme.in"],
  "cc":         ["accounts@acme.in"],
  "subject":    "Credit note CN-2026-0015 against INV-2026-0042",
  "body_html":  "<p>Hi Priya,</p><p>Please find attached credit note <b>CN-2026-0015</b> for ₹11,800 against invoice INV-2026-0042 (returned items).</p>",
  "attach_pdf": true
}

Sample response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "code":    0,
  "message": "The credit note has been emailed.",
  "delivery": {
    "message_id":   "0102018a-4d1f-7c2b-9a0e-7f6b3c8e1d24-000000",
    "from":         "billing@acme.in",
    "to":           ["priya@acme.in"],
    "cc":           ["accounts@acme.in"],
    "bcc_count":    0,
    "subject":      "Credit note CN-2026-0015 against INV-2026-0042",
    "attached_pdf": true,
    "pdf_filename": "CN-2026-0015.pdf",
    "pdf_size":     72944,
    "sent_at":      "2026-05-12T08:35:42Z"
  }
}

Errors

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "code":    "validation.failed",
  "message": "Body shape invalid.",
  "errors": [
    { "field": "to", "code": "required", "message": "to[] must contain at least one address." }
  ]
}
CodeHTTPWhen
not_found.resource404The document doesn't exist in this org.
validation.failed422Body shape invalid (e.g. to empty).
email.send_failed502SES rejected the message. The error message includes the SES reason — usually a malformed recipient or sandbox-mode restriction.
auth.insufficient_scope403Token lacks UPDATE on the resource.

Operational notes

  • The org's sender address is set in Settings → Email (e.g. billing@yourdomain.com) and must be verified in SES.
  • Attached PDF size counts against SES's 10MB raw-message limit. With FinzBooks invoice templates the rendered file is typically well under 1MB.
  • Every successful send fires an EMAIL_SENTentry in the activity timeline of the source document — so partner apps can show a “Sent to alice@acme.in 2 days ago” row without tracking it themselves.