How to Email a Daily NetSuite Sales Order Report as a CSV

Pull yesterday's NetSuite sales orders on a schedule, build a CSV, and email it as an attachment with Resend.

What This Integration Does

Finance and operations teams often want a plain daily snapshot of sales orders in their inbox - no dashboard login, no NetSuite saved search to maintain. This Spojit workflow runs every morning, pulls the previous day's sales orders from NetSuite, turns them into a CSV, and emails that file to whoever needs it.

It is triggered on a schedule, reads a rolling one-day window so each run covers only new orders, and leaves no state behind - the CSV is generated fresh and sent each run, so re-running simply produces and sends the same report again. There is nothing to clean up between runs.

Prerequisites

  • A netsuite connection with SuiteTalk REST access enabled.
  • A resend connection with a verified sending domain.
  • The recipient address (or list) for the daily report, and a sender address on your verified domain.

Step 1: Schedule Trigger

Drop a Trigger node onto the canvas and set its type to Schedule. Pick a time shortly after midnight in your account's timezone - 06:00 daily is a common choice so the report is waiting when the team logs in. The run time defines "today", and you will look one day back from it in the next step.

Step 2: Compute the One-Day Window

Add a Transform node to work out the date filter for the query. Compute a single value:

  • since - the start of yesterday, formatted the way the NetSuite filter expects (for example MM-DD-YYYY).

This keeps each run incremental: you only ask NetSuite for orders dated on or after yesterday, rather than re-pulling the whole table. If you would rather report on a fixed calendar day, compute both a start and an end value and use them as a range in the next step.

Step 3: Pull Sales Orders from NetSuite

Add a Connector node pointing at the netsuite connector and pick the list-sales-orders tool. Set the q filter to scope the results to your window, and raise limit to cover a busy day:

q:     tranDate ON_OR_AFTER '{{ since }}'
limit: 1000

If you need a custom column set or a precise start-and-end window, swap this step for the run-suiteql tool on the same connector and write a SELECT against the transaction table filtered to type = 'SalesOrd'. For most daily reports, list-sales-orders is enough.

Step 4: Transform - Flatten Orders into Rows

NetSuite returns nested order records. Use a Transform node to project just the columns your report needs into a flat array of objects - one object per order. A typical shape:

[
  {
    "orderNumber": "{{ order.tranId }}",
    "date":        "{{ order.tranDate }}",
    "customer":    "{{ order.entity.refName }}",
    "status":      "{{ order.status.refName }}",
    "total":       "{{ order.total }}"
  }
]

Keep the keys clean and human-readable - they become the CSV header row in the next step. Wrap the projection in a Loop if you prefer to map orders one at a time.

Step 5: Build the CSV (base64-encoded)

Add a Connector node pointing at the csv connector and pick the from-json tool. Pass the flat array from the previous step as data, keep header enabled so the column names appear as the first row, and set encoding to base64. The tool returns the finished CSV on its csv output field, already base64-encoded - exactly what an email attachment needs, so there's no separate encode step.

Step 6: Email the Report with Resend

Add a Connector node pointing at the resend connector and pick the send-email tool. Fill in the recipients and a short body, then attach the CSV:

  • to: the report recipient(s)
  • subject: Daily sales orders - {{ since }}
  • html: a one-line summary, e.g. the number of orders in the file
  • attachments: [{ "filename": "sales-orders-{{ since }}.csv", "content": "{{ csv }}" }] - {{ csv }} is the base64 output from Step 5

On the next scheduled run, Spojit pulls a fresh day of orders and the report lands in the recipient's inbox automatically.

Tips

  • Send to a group, not a person - point to at a distribution list so the report keeps flowing when individuals are on leave.
  • Skip empty days - add a Condition node after Step 3 that checks the order count, and only build and send the CSV when there is at least one order.
  • Name the file by date - putting {{ since }} in the filename means recipients can archive a run of daily reports without overwriting one another.

Common Pitfalls

  • Timezones - NetSuite tranDate is in the account timezone. Compute since in that same timezone or a report run just after midnight can miss or double-count boundary orders.
  • Date format - the SuiteTalk q filter is picky about date format. Match the format NetSuite expects (commonly MM-DD-YYYY) or the filter silently returns everything.
  • Use base64 output, not plain text - email attachments must be base64. Set the csv from-json tool's encoding to base64; passing the plain (utf8) CSV into attachments produces a corrupt file.
  • High-volume days - if you regularly exceed the limit, page through results with offset and concatenate before building the CSV.

Testing

Run the workflow once manually with since hard-coded to a recent busy day, and set to to your own address. Open the email, download the CSV, and confirm the header row and a few orders look right - order numbers, dates, and totals should match NetSuite. Once the file looks correct, point to at the real recipients and turn the schedule on.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.