Send a nightly order export to a partner's SFTP
A partner, a third-party logistics provider or an ERP wants your orders as a file in a folder by morning. This guide sets that up with the official Orders CSV export to SFTP template in Integration Studio: the schedule fires, the platform exports the orders, the file lands on the partner's server under a dated name, and a small marker file, a signal file the partner waits for, tells the partner it is complete.
It is for developers and integrators who run the partner connection. You need a tenant with Integration Studio and Import & Export, permission to open Integration Studio in Cockpit, the partner's SFTP host, account and folder, and an API key carrying the io scope. Nothing is installed locally. The opposite direction, a supplier's file coming in on a schedule, is covered by Import a BMECAT catalog.
1. Create the two credentials
The export needs two credentials under Integration Studio → Credentials:
- A Revenexx API credential with the
ioscope. It runs the export and fetches the result. - An SFTP credential for the partner's server. Test it in the dialog before you save.
The simplest setup is a partner server reachable from the public internet. File nodes have no fixed outbound addresses to allow-list, and a server inside a private network is reachable only if your tenant has a VPN route that the SFTP credential is set to use, which newer releases support and this guide did not verify on your tenant (as of 2026-11). See File transfer for the details. Ask the partner for an account that can write into one folder and nowhere else; that restriction is theirs to enforce on their server.
2. Install the template
Open Integration Studio → Templates → Orders CSV export to SFTP and read its page first. It shows the steps in run order, the variables you can tune (the same list you can read later in the copy's workflow settings in Cockpit), and a readiness check that counts the credentials and secrets it needs against your tenant. Press Use template, name the copy, and pick the two credentials from step 1.
You get a paused copy. As far as can be told, it is wired as the diagram shows: a schedule trigger, an Ensure Profile exists step that creates the export profile, Export from profile and Deliver to SFTP. The template's definition is not published, so compare the copy with the diagram and trust the copy. Nothing is linked back to the template afterwards, and nothing runs until you activate the copy. See Templates for what to adjust after installing.
Open the copy and read three things before you change anything:
- Its variables. Open the copy in Cockpit and read its variables there; this guide cannot list them. Give every one a value. An empty variable resolves to nothing, silently.
- The export profile. On its first run the workflow creates an export profile for the orders entity, named
[wf] Orders CSV Export, and the template is meant to leave your later edits alone. It decides which columns the file carries. If edits to the profile disappear, check the Ensure Profile step's update mode: Always sync overwrites them on every run. After the first run, read it withGET /v1/io/profilesand look atmapping.fields. An emptymapping.fieldsmeans every column of the entity, in the table's own order and names. That includes personal data: an order row carries thebuyer,billing_addressandshipping_addressobjects, pluspayment,shippingand free-formuser_dataandmetadata. Edit the profile somapping.fieldslists only the columns the partner needs (an ordernumber,status, totals and line references are usually enough), and agree with your data-protection contact what the partner may receive. See Import and export for the profile calls. - The Deliver to SFTP step. Its target path and base directory are the next steps.
Installing happens in Cockpit. The Integration Studio API can also do it, but with the token of a signed-in person, not an API key (see Integration Studio).
3. Set the schedule and timezone
The schedule trigger takes a five-field cron expression and an IANA timezone, and the copy ships with ones that suit a generic customer. Change both:
30 3 * * * Europe/Berlin
- Pick the timezone the partner reads the file in. A partner who expects the file "first thing" means their morning, not yours.
- Run after midnight UTC with room to spare. The orders app stamps each order with
placed_on, the UTC day of when it was placed (or created, if it was never placed). A run at 02:00 in Berlin is exactly midnight UTC in summer, so a filter for the finished day can miss the last orders. 03:30 leaves margin all year. - Saving is not firing. The first run is the next matching clock time. To see the whole flow now, run the workflow by hand from a manual trigger (add one if the copy has none; a workflow may have only one). The step-by-step check is in step 8.
Do not save the workflow around the time it fires: a save queues a build, and a firing during the build becomes a missed run. Schedule triggers has the full rules, including why a firing is not exactly-once.
4. Decide what goes in the file
The Export from profile step runs the profile and waits for the job. It has an optional Filter field that takes a list of terms as JSON. Terms in one list are combined with AND, and a filter you set replaces any filter stored on the profile. A term names a column of the orders entity, an operator, and a value:
[
{ "column": "status", "op": "not_in", "values": ["pending", "cancelled"] }
]
The operators are eq, ne, lt, lte, gt, gte, in, not_in, like, ilike, is_null and not_null. lt, lte, gt and gte compare in the column's own type (number, date, timestamp), so on a text column such as number they compare as text; the others always compare as text. Every value is a string. Single-value operators take value and only in and not_in take a values list, so a day slice is [{ "column": "placed_on", "op": "eq", "value": "2026-11-02" }]. Useful columns on an order are number (unique per tenant), status, payment_status, placed_on (a date), placed_at, updated_at and channel_id. The export service applies the filter, and the API reference does not list it yet (as of 2026-11).
Two shapes work today:
- The full export, with a partner who upserts. Leave the filter alone, or narrow it by status as above. Keep
cancelledorders in if the partner needs to hear about cancellations. Every night's file holds every matching order, and the partner updates what it already has, keyed on the ordernumber. This is the shape that needs no date at all. A missed night repairs itself the next night. The cost is a file that grows with your order history. - A day slice from a date you supply. Filter on
placed_onwitheqand a date such as2026-11-02. The date has to come from somewhere you set: a workflow variable you change, or the data of a manual run. That is the right shape for re-sending one day the partner lost, and a poor one for a nightly job, because nothing computes the previous day for you. The Date Time node formats "now" or a date you give it, with no offset, and expressions read values without computing them. See Expressions.
Set Max attempts to 1 on the Export from profile node (its Settings tab), or keep the export well under the node's 10-minute default timeout. A retry starts the whole step again and queues another export, so a slow export that times out can leave one run with two or three exports (as of 2026-11, read from the node's code, not tested). See Failure handling.
If the partner needs a rolling "yesterday" and cannot upsert, that is not buildable from the shipped nodes today (as of 2026-11). Do not fake it with a date you edit by hand each evening.
5. Name the file and pick the folder
Deliver to SFTP streams the export result onto the partner's server without holding the file in the workflow, so a large file is an ordinary case. Its Target path field takes two placeholders, {date} and {datetime}, which the node fills in when it runs. It also takes expressions:
/outbox/orders-{date}.csv
For the 3 November 2026 this produces /outbox/orders-2026-11-03.csv. Settings worth deciding before the first night:
- Base directory. Set it to the partner's folder, here
/outbox. The node refuses any target path that leaves it, before it connects. The field starts empty, which means no check at all, so fill it in. - Overwrite existing file. The default is on. Step 7 says when to turn it off.
- The day the name carries. The timezone
{date}uses is not documented (as of 2026-11). Check the first file's name against the time of its run before you tell the partner what to expect.
Agree the name pattern, the folder and the file's columns with the partner before the first delivery. Changing a column order later breaks their import silently.
6. Tell the partner it is ready
A file that appears in a folder is not necessarily finished. The platform does not write a marker file for you. Deliver to SFTP writes exactly one file, so the marker is a step you add after it. ${{ run.id }} below is an expression that resolves to the id of the current run:
- Add an SFTP: Upload File node on the
outport of Deliver to SFTP, with the same SFTP credential. - Set its Path to a fixed name beside the file, for example
/outbox/orders.ready. - Set Data to text the partner can use, for example
${{ run.id }}, and Encoding to plain text.
/outbox/orders-2026-11-03.csv
/outbox/orders.ready
The marker is written only when the delivery succeeded, so a failed night leaves no marker. Tell the partner the convention: fetch the CSV only when orders.ready exists, and delete the marker after fetching. The same convention works in the other direction, with the SFTP: File Exists? node as the gate; see File transfer.
A fixed marker name is overwritten every night. If the partner did not delete yesterday's marker, the new marker looks the same as the old one. Put the CSV's date into the marker's content if the partner needs to tell them apart, or ask them to delete it as part of their pickup.
7. Make a double or missed firing harmless
The platform does not promise exactly one run per firing. One firing can become two runs, and a firing can be skipped. Plan for both.
A firing that runs twice. Both runs write the same dated path, and each runs a fresh export. With Overwrite existing file on, the second run replaces the file with a new export of the same orders plus any that changed in between, and writes the marker again, so a partner who already picked the file up sees the marker a second time. With overwrite off, the second run's delivery is refused with the error code FILE_EXISTS, on the node's error output, and the existing file stays. Add an If condition on the error port that tests ${{ in.code }} equal to FILE_EXISTS, route its true branch to a No Operation node so the run ends as a success, and send every other error on to your failure handling. FILE_EXISTS is returned, not thrown, so it is not retried. Turning overwrite off also means the node removes a half-written file of its own if a delivery breaks, so a retry can start clean. Either way, the partner's import has to tolerate seeing a file twice, so ask them to upsert on the order number.
A firing that never happens. A platform that was down at the tick does not fire it late, and a firing that arrives while the workflow is rebuilding is kept under Integration Studio → Runs → Missed runs, where you can replay it. A tick the platform never fired is not recorded anywhere, so the partner is your detector: agree that no marker by a set time means "ask us". See Missed runs. With a full export the next night's file covers the gap. With a day slice you re-send the missing day by hand, as in step 4.
A failed night. Nodes retry on their own, three attempts by default, and nothing notifies you. Route the error ports to a Send Email node and read the runs each morning, as described in Keep an Integration Studio workflow running.
8. Run it once and read the result
- Run the workflow from its manual trigger (see step 3 if the copy has none). Do this against a test folder on the partner's server, or with the partner's agreement, because a manual run writes a real file.
- Open the run under Integration Studio → Runs and read each step's input and output.
- Check on the server that
orders-<date>.csvandorders.readyexist, and that the file has the columns you and the partner agreed. - Run it a second time and confirm the behaviour you chose in step 7.
- Activate the workflow.
Troubleshooting
- The export step fails with an authorization error. The API credential tests fine but lacks the
ioscope. A credential check does not test scopes. PATH_OUTSIDE_BASE. The node refused the path before connecting. Check for..that climbs out of the base directory, an absolute path in another folder or with different letter case (/OUTBOX/...), a backslash, or a base directory entered without its leading/. A relative path without a leading/is not refused: it is placed under the base directory.- The partner's file is empty or cut off. With overwrite on, a delivery that breaks midway leaves a half file. The marker is missing too, which is the signal not to read it. Turn overwrite off, or rerun the workflow by hand.
- Orders from the last hours are missing. The filter used
placed_on, which is the UTC day, and the run fired before that day finished. Move the schedule later. - A filter fails the run. The column is not one of the orders entity, an operator is misspelled, or
inhas no values. A filter the node cannot read as a list of terms stops the run withINVALID_SCOPErather than exporting everything. - One night produced two or three exports. The Export from profile step timed out or failed while its job was still running, and each retry queued a new export. Set Max attempts to 1 on that node, as in step 4 (as of 2026-11).
- No file after the schedule time. Check Missed runs and the workflow's build status before anything else.
Where to go next
- Keep an Integration Studio workflow running — read a failed night, retry, resume and replay. Start here once the first night has run, because nothing notifies you when a run fails.
- File transfer — the SFTP nodes, the archive pattern and the marker convention.
- Schedule triggers — cron, timezone and the firing rules.
- Import and export — the
/v1/ioAPI and profiles behind the export step. - Import a BMECAT catalog — the same template pattern in the inbound direction.
- Hand an order to the ERP — when the partner needs each order as it is placed, not a nightly file.