Answer first
Every outbound document — invoice, proposal, work order, statement, credit note, quote request, contractor agreement — travels inside a branded email built from a tenant template. update_pending_send lets you overwrite two slots on a single staged send without touching that template:
cover_message— a personal note, plain text, up to 2000 characterssubject— the email subject line, up to 200 characters
Both are per-send. Neither changes the tenant's boilerplate for anyone else.
Where it sits in the send chain
Sends are staged, never one-shot. The personalisation slot only exists in the middle of the chain:
propose_send_invoice(invoice_id)
→ returns operation_id, recipients[], email_preview
update_pending_send(operation_id, cover_message, subject?)
→ returns the re-rendered email_preview
confirm_pending_operation(operation_id)
approve_send_invoice(operation_id, confirmed: true)
→ email dispatched
You may call update_pending_send as many times as you like before approving. Nothing has left the building until the approve leg returns send_ok: true.
How the note renders
The composed email is assembled in this order:
- Template greeting —
Hi <resolved name>, - your
cover_message, as a single paragraph - Template boilerplate — e.g.
Please find your invoice from <business>. - Amount / due date / terms table, payment CTA, bank details
- Template sign-off and footer
Three rules follow directly from that ordering, and each one is a real mistake people make:
Write no greeting. The template already opened with one. A cover_message starting Hi Sam — produces a visible double greeting.
Write no sign-off. The template already closes. Adding Thanks, Sam gives the email two endings.
Write one paragraph. The slot renders inside a single HTML paragraph element, so newlines you type do not survive into the delivered email. Two or three sentences that flow is the right shape.
Check the resolved greeting name before you write
The greeting is not always a person. It resolves to the contact name when the client has a contact flagged to receive that document type, and falls back to the client's legal name otherwise — which can be a company name in block capitals.
The recipients array returned by the propose leg tells you which you got:
"recipients": [
{ "email": "...", "name": "Sam Whitfield", "resolved_from": "receives_invoices" }
]
If the resolved name is a company rather than a person, and you know the individual, drop their first name into the first sentence of your note instead of the greeting — "Thanks for the payment you made last week, Sam — that one was against...". You get the personal touch without fighting the template.
Read the array for a second reason: it is the exact fan-out the approve leg will email. An unexpected address here is a contact-configuration problem to fix before sending, not after.
The preview is the email
update_pending_send returns a fresh email_preview containing subject, body_html and body_text. This is not an approximation — it is what will be dispatched. Read it, not your intent.
Worth confirming every time: your note landed above the payment CTA, the recipients are right, and the amount and due date match what you expect.
Changing recipients or attachments
You cannot. update_pending_send edits wording only. To change who receives the email or what is attached, cancel the operation with cancel_pending_operation and propose it again against corrected records.
The staging window
A staged operation expires if it is not approved — tenant-tunable via finance.sends.pending_operation_ttl_minutes (default 60, clamped 5–240). An expired operation sent nothing and changed nothing; stage it again.
Because cancelling is free and non-destructive, staging a send purely to read the preview and then cancelling is a legitimate way to inspect an email before committing to it.