Send documents to customers with PDF attachments and customizable templates.
Send
// title: Send invoice email
await sdk.email.sendEmail({
document_id: invoice.id,
to: "customer@example.com",
subject: "Invoice #{document_number}",
body_text: "Please find your invoice attached.",
});Uses the entity’s default email template for the document type and locale.
PDF Attachment
Control what gets attached to the email:
| Option | Type | Default | Description |
|---|---|---|---|
attach_pdf | boolean | false | Attach the document as a PDF file |
attach_eslog | boolean | false | Attach e-SLOG 2.0 XML (Slovenian format) |
language | string | entity locale | Override the PDF and shareable link language |
Both attach_pdf and attach_eslog can be combined in a single email.
Your Own Files
Upload files to an issued document with POST /files, category: "attachment" and document_id (an invoice, estimate, credit note, advance invoice or delivery note ID). A document holds up to 10 files of up to 5 MB each and 6 MB in total (an email can be at most 10 MB once encoded); accepted types are PDF, PNG, JPEG, WebP, GIF, Word and plain text. List them with GET /files?document_id=....
Every file attached to the document is included when the document is emailed, after the PDF and e-SLOG files. To leave some out of one email, pass their IDs:
| Option | Type | Default | Description |
|---|---|---|---|
exclude_attachment_ids | string[] | none | Up to 100 file IDs to leave out of this email. Unknown IDs are ignored. |
exclude_all_attachments | boolean | false | Send without any of the document’s files; takes precedence over exclude_attachment_ids. The PDF and e-SLOG options are unaffected. |
Permanently deleting a draft also deletes its files.
Default Templates & Multi-Language
When you create an entity, default email templates are automatically generated for each document type. Templates use the entity’s locale by default.
20 locales are supported for locale and language: en-US, en-GB, de-DE, it-IT, fr-FR, es-ES, sl-SI, pt-PT, nl-NL, pl-PL, hr-HR, sv-SE, fi-FI, et-EE, bg-BG, cs-CZ, sk-SK, nb-NO, is-IS, hu-HU.
English content translations (translations.* on entity settings, documents and items) are keyed en-US: there is no en-GB translation key, and a request for en-GB (or en) uses the en-US content. English entities (en-US, en-GB, en-AU, …) use their own default content for any English language.
An entity’s locale can also be a regional English tag (en-IE, en-AU or en-NZ): dates and amounts are formatted for that region and the wording follows English (UK). Ireland, Australia and New Zealand entities default to these.
Override the language per-email by passing the language option.
Payment Reminder Links
Manual and automatic payment reminders link to each invoice on the canonical frontend domain for the entity’s production or sandbox white-label environment. Entities without a white-label domain use the standard Space Invoices frontend. An explicit reminder locale or language override is retained in the link’s language query parameter.
Document Links in Your Own Portal
White-label account owners and admins can set a Document link template in Account → White labels. When set, the document link in sent emails ({invoice_link} and the automatically added “View document” link) and in payment reminders uses this URL instead of the hosted document page. The shareable_link returned when sending also uses it.
The template must be an https:// URL that includes {shareable_id}. You can also use {document_type} (invoice, estimate, credit_note, advance_invoice, delivery_note or purchase_order) and {language} (the explicit language override, otherwise the entity locale). Templates can’t contain spaces, ( ) [ ] < >, quotes or backticks, and placeholders can’t be used in the host or in query parameter names. For example:
https://portal.example.com/invoices/{shareable_id}?lang={language}Your portal can show the document with the public shareable endpoints, such as GET /invoices/shareable/{shareable_id} and GET /invoices/shareable/{shareable_id}/pdf. These need no API key. Unsharing a document still disables its link.
Optional Customization
The basic send uses the default sender and template. Configure the following only when you need your own sender address or email copy.
Verified Custom Sender Addresses
Production entities can send document emails and payment reminders from a verified address such as billing@example.com. Configure an entity sender in Settings → Email, or use the entity sender API.
White-label account owners and admins can also configure an inherited sender in Account → White labels. White-label sender management is an account-admin dashboard feature and is not exposed through the public API.
Sender Precedence
Only a fully verified custom sender is used for delivery. The effective From address is selected in this order:
- Verified entity sender
- Verified sender inherited from the entity’s production white label
- Platform default sender
Saving a pending or failed entity sender does not interrupt delivery; Space Invoices continues using the next verified sender in the list. The sender configuration response returns configured, inherited, and effective so you can see both verification state and the address currently used.
Verification Flow
- Set the entity sender. The address is normalized and reserved to the account.
- Complete the verification message sent to the email address.
- Add the returned
domain_dkim_tokensas CNAME records in the sender domain’s DNS. - Recheck verification after DNS changes propagate. Rechecking reads status only and does not resend verification.
- Confirm that
effective.sourceisentityandeffective.verifiedistruebefore relying on the custom address.
Both the email address and its domain must be verified. Entity admins and account owners/admins can set, clear, or recheck an entity sender. Clearing an override restores sender inheritance, but intentionally does not release the address for use by another account.
The same normalized email address cannot be claimed by multiple accounts. A 409 response means the identity is already reserved; a 503 means the verification provider is temporarily unavailable and the request can be retried.
Custom Template
// title: Custom email template
await sdk.email.sendEmail({
document_id: invoice.id,
to: "billing@acme.com, accounts@acme.com",
subject: "Invoice {document_number} from {entity_name}",
body_text: `Hi {customer_name},
Please find invoice **{document_number}** attached.
**Amount due:** {total_with_tax} {currency_code}
**Due date:** {due_date}
View online: {invoice_link}
Thank you for your business!`,
});Use the template variable reference to personalize the subject and body.
Markdown Formatting
The body_text field supports Markdown formatting. Bold, italic, links, and lists all render correctly in the email. HTML tags and images are stripped for security.
Sending Limits and External Review
Suspicious sends on free and trial accounts may undergo an EU-hosted abuse review using a minimised, scrubbed email and document summary. Paid accounts and white-label sends without a classified free or trial plan are excluded from this review. Existing sending limits and other safeguards still apply; review blocks return 403 and exceeded sending limits return 429.
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Variable shows as empty | Document or customer field is null | Ensure the referenced field is set before sending |
| Email not received | Recipient address invalid or blocked | Check the to address; review bounce logs in dashboard |
| Custom sender is not active | Email or domain verification is still pending | Complete email verification, add every returned DKIM CNAME record, then recheck status |
| Sender update returns 409 | The normalized address is reserved to another account | Use another controlled address or contact support if ownership needs investigation |
| Sender update returns 422 | Custom sender verification was attempted in sandbox | Configure the sender on a production entity or production white label |
| Sender update or recheck returns 503 | The verification provider is temporarily unavailable | Retry later; the existing effective sender remains in use |
| Rate limited (429) | A per-document or sandbox account send limit was reached | Wait for the returned Retry-After duration before retrying |
| PDF not attached | attach_pdf not set | Pass attach_pdf: true in the send options |
| Send returns 400 about email or attachment size | The email with its PDF and files would exceed 10 MB, or the files left in exceed 6 MB together | Pass some files in exclude_attachment_ids, or send without attach_pdf |
| Wrong language on PDF | Entity locale differs from customer | Pass language option to override |
Template Reference
Use this reference when writing a custom template.
Template Variables
Variables are wrapped in curly braces and replaced automatically when the email is sent.
Entity Variables
| Variable | Description |
|---|---|
{entity_name} | Your company/organization name |
{entity_email} | Entity email address |
{entity_address} | Street address |
{entity_city} | City |
{entity_post_code} | Postal/ZIP code |
{entity_country} | Country |
{entity_tax_number} | Tax/VAT number |
{entity_company_number} | Company registration number |
Document Variables
| Variable | Description |
|---|---|
{document_number} | Invoice or estimate number |
{document_date} | Issue date (localized) |
{document_due_date} | Payment due date (localized) |
{document_valid_until} | Estimate validity date (localized) |
{document_total} | Total amount with tax (2 decimal places) |
{document_currency} | Currency code (e.g., EUR, USD) |
Customer Variables
| Variable | Description |
|---|---|
{customer_name} | Customer’s name |
{customer_email} | Customer’s email |
Bank Account Variables
| Variable | Description |
|---|---|
{bank_account} | Full bank account details (multiline) |
{bank_account.iban} | IBAN |
{bank_account.account_number} | Account number |
{bank_account.bank_name} | Bank name |
{bank_account.bic} | BIC/SWIFT code |
{bank_account.name} | Account holder name |
{bank_account.routing_number} | Routing number (US) |
{bank_account.sort_code} | Sort code (UK) |
Date Variables
| Variable | Description |
|---|---|
{current_date} | Today’s date (localized) |
{current_year} | Current year |