Skip to main content

Preview Bulk Customer Email

POST 

/api/sales-orders/bulk-email/preview

Resolves and groups a bulk-email selection without sending anything, powering the confirmation dialog's recipient summary and a masked sample render. Accepts the exact same body as POST /sales-orders/bulk-email.

Required scope: orders:write

Grant this scope to your token under Settings → Developer → Personal Access Tokens.

Authentication: Requires Bearer token.

Request body (scope: one of ids or filters is required):

  • ids (array of int, required without filters): Sales order IDs to email about.
  • filters (object, required without ids): Filter set that resolves to a list of sales order IDs (same shape used by the V2 sales-orders listing endpoint). Combine with apply_to_all.
  • apply_to_all (bool, optional): When true, the action targets every order matching the active filters rather than an explicit ids list.
  • template_id (int|null, optional): The bulk_sales_order store email template the content was loaded from. Null when the body was composed ad hoc.
  • subject (string, required, max 998): Email subject. Supports {{customer_name}}, {{order_count}}, {{store_name}} tokens.
  • html_body (string, required): Email body HTML. Supports the same tokens plus {{orders_table}} (renders the customer's grouped orders as a table).
  • cc (array of email, optional, max 25): CC addresses added to every email.
  • attachments (array of string, optional, max 25): Attachable-document keys to include (e.g. ["invoice_pdf"]).
  • group_by_customer (bool, optional, default true): Group every selected order for one customer (same store + email) into a single email (Cin7 Omni model). When false, one email per order.
  • skip_without_email (bool, optional, default true): Orders with no resolvable email are always skipped. Must be true — sending false is rejected (422).
  • respect_opt_out (bool, optional, default true): Skip customers flagged email_opt_out.

Response data:

  • order_count (int): Total orders resolved from the selection.
  • email_count (int): Distinct emails that will be sent (after grouping + cap).
  • skipped_no_email (array of int): Order IDs with no resolvable email.
  • skipped_opted_out (array of int): Order IDs whose customer opted out.
  • skipped_overflow (int): Recipients beyond the cap that would be dropped.
  • groups_preview (array, max 50): Per-recipient summary with a masked email, order_count, and order_numbers.
  • sample (object|null): First group's masked recipient plus the rendered subject and body HTML; null when no group is emailable.

Requires permission: sales_orders.update

Request

Responses

OK

Response Headers
    Content-Type