Connecting Azure Logic Apps to SFTP To Go

Azure Logic Apps is Microsoft’s cloud-native low-code platform for automating workflows and connecting systems without extensive programming. Logic Apps feature a visual designer and a wide range of connectors to ingest, transform, and route data across cloud environments and external platforms.

This guide walks through the benefits of using Azure Logic Apps with SFTP To Go and explains how to create a new Logic App and trigger it with webhooks.


What makes Azure Logic Apps useful for file transfers?

In workflows built around an SFTP server, Logic Apps typically serve as the execution engine for secure file transfers with built-in business logic. They ingest inbound files, validate and transform their contents, and route the results to their next destination.

Here are some of the good reasons to use them for file transfers that involve SFTP To Go specifically:

  • Event-driven file processing. SFTP To Go can send a webhook to a Logic Apps HTTP trigger whenever a file event occurs, such as an upload, so workflows start as soon as a file lands instead of waiting for a polling interval.
  • Flexible file movement and routing. Logic Apps can pick up new files from an SFTP folder and automatically route them across destinations like Azure Storage, Service Bus, or an SQL database.
  • Enterprise trading partner integrations. Organizations can ingest partner files that are dropped onto an SFTP server, parse formats like ANSI X12 or EDIFACT, and map the data directly into ERP or CRM systems.
  • IT-governed deployments. On the Standard tier, you can store workflows as code, manage them via Git, run automated CI/CD pipelines, enforce code reviews, and track multi-environment deployments.

Naturally, Logic Apps are not the proverbial silver bullet, so there are things you need to take into consideration:

  • Expression language friction. Logic Apps handles data routing well, but basic string operations require more boilerplate than commonly used programming languages. For example, extracting a parent directory from a file path turns into a nested expression that involves index searching and string slicing. In languages like Python or Go, it would take a single helper function.
  • Content and metadata are separate calls. The Get file content using path action doesn't return the modified time or other metadata, so you need extra actions and extra cost.
  • Cost model. On the Consumption tier, you pay per action execution, so high-volume file flows add up. The Standard tier has a different pricing model with a baseline cost.
  • Connector limits. The SFTP-SSH connector has file size limits (1GB) and relies on chunking for large files. You are also allowed only 150 API calls and 1000MB bandwidth per 60 seconds.

Before building anything, you’ll have to make a few design decisions. SFTP To Go exposes the same underlying data through different interfaces, so which connector should actually drive the workflow?


Choosing the right architecture: webhooks, SFTP-SSH, or Amazon S3

Two decisions define the design of an app that manages transfers between SFTP To Go and another location: how the Logic App learns that a new file has arrived (the trigger), and how it then reads, writes, or deletes files (the action connector).

New file discovery

You have three options here:

  • Outbound webhooks from SFTP To Go captured by the HTTP request trigger.
  • The When a file is added or modified trigger from the SFTP-SSH connector that polls SFTP To Go over SFTP.
  • The When an S3 object is updated trigger from the official Amazon S3 connector.

Both SFTP-SSH and Amazon S3 connectors are applicable because SFTP To Go serves a managed SFTP endpoint built on top of AWS with S3 as the back-end storage.

For file event discovery, outbound webhooks from SFTP To Go are a perfectly valid alternative that can help you avoid the resource overhead of continuous polling.

At the same time, it’s a good idea to keep concurrency controls in mind. The HTTP trigger processes requests instantly and lacks built-in throttling by default. If a user uploads thousands of files at once to SFTP To Go, the HTTP trigger will spin up thousands of concurrent Logic App instances instantly because its default behavior is unlimited parallel execution. This will likely crush a downstream SQL database.

To protect your infrastructure, you may want to enable concurrency control on the trigger to limit parallel execution. Just keep in mind that Logic Apps caps the concurrency at a maximum of 100 parallel runs.

Managing files on storage

You have two options for the decision on what to manage files with:

  • Create, copy, delete, and other actions from the SFTP-SSH connector.
  • Similar actions from the third-party Amazon S3 Bucket (Independent Publisher) connector.

This is where things go hairy for S3-centric workflows. The official connector doesn't currently support writing or deleting objects at all. It's limited to reading content and metadata and listing buckets, objects, and regions. So for managing content in the bucket, you’ll have to complement it with that 3rd-party connector that comes with caveats of its own:

  • Separate, non-shareable connections: you can’t reuse a connection over the S3 API that you may have already created with the official connector, and vice versa.
  • Strict throttling limits: only 100 API calls per minute, while the official connector supports up to 6,000 API calls per minute.
  • The connector is still in preview, which could be a turn-off for companies with strict policies.
💡
Note: the SFTP-SSH connector and the official Amazon S3 connector are not directly comparable for yet another reason: S3 and SFTP are fundamentally different entities. One is a flat object storage service, while the other is a network protocol that exposes a genuine hierarchical filesystem. So while there is some overlap in functionality between the two connectors, they aren't and will never be the same. 

Which option to pick

Let’s sum it up.

Use the S3 connectors when:

  • You only need to read, monitor, or list objects, or you are fine with various limitations a 3rd-party connector will impose on you when you need to manage objects.
  • You're already standardized on S3-style access keys elsewhere in your architecture and want one consistent credential model, rather than adding SSH credentials into the mix.
  • Your objects are small (the Get S3 object content action caps out at 3.5 MB) and key-based lookups on a flat structure are enough.

Use the SFTP-SSH connector when:

  • Your workflow needs to create, rename, move, or delete files over the same connection.
  • You want real folder-based organization rather than emulating structure through key prefixes.
  • Your partner or process already authenticates with SFTP credentials rather than AWS IAM keys.

Use SFTP To Go webhooks with HTTP triggers when:

  • You need near real-time, event-driven processing without burning API calls on constant polling loops.
  • You want to decouple your workflow activation from heavy storage integrations and let an HTTP webhook payload point directly to the file path that needs processing.
💡
Note: this is not a deathmatch between connectors. You can mix all of them up as the workflow dictates. For this guide specifically, we’ll rely on both webhooks and the SFTP-SSH connector.

Example project brief and prerequisites

Let’s build a quick project to get a better understanding of how the platform connects to external services like SFTP To Go. Here is what our simple Logic App will do:

  1. Wait for an incoming HTTP request sent by SFTP To Go whenever a new file is uploaded.
  2. Read the file content and its modification timestamp (modstamp).
  3. Compose a new filename that appends the modstamp to the original filename.
  4. Copy the file under that new filename to a different folder on SFTP To Go. 

On the SFTP To Go’s side, the outbound webhook will be monitoring the inbound directory and sending HTTP requests when new files are uploaded.

💡
Note: SFTP To Go’s built-in automations can handle such a task without triggering external apps. This example merely serves the purpose of demonstrating how to read, write, and manipulate data and metadata in Azure Logic Apps.

Here’s what you need to have in order to follow this guide from start to finish:

  • An admin account in your organization on SFTP To Go. You need it to create new credentials (should you require any) and automations.
  • SFTP credentials for the Logic App connection. You can look them up on the Credentials page in the dashboard.
  • An Azure subscription (a free one works for testing) with at least Contributor access to a resource group.

Creating a new Logic App

Log in to Azure, type Logic Apps in the search panel at the top, and go to that section:

Click + Create and select the hosting option. For the purpose of this guide, select Consumption - Multi-tenant:

Select a subscription and a resource group, then give the Logic App a name. It’s usually a good strategy to have a naming convention for various resources so that it’s easy to distinguish between similar items:

After that, select a region where your app will be operating. This is important for data residency compliance, proximity to core systems, and disaster recovery setup.

Click Review + create to quickly bypass other settings and keep them at defaults. Azure will run settings validation. If everything’s fine, click Create to finalize the Logic App creation. Azure will initialize app deployment:

Click Go to resource to proceed.


Designing a Logic App that interacts with SFTP To Go

Since the webhook will need the Logic App’s URL to work, let’s start with defining a trigger in the Logic App.

Step 1. Set the trigger

On the left, click on Development Tools to expand the group and select Logic app designer. Please note that for this guide, we’ll be using the preview version of the new interface: it fixes some issues of the original one and is what you’ll likely be dealing with by default soon enough. 

This is where you create your app:

Every logic app starts with a trigger that responds to a specific event and takes a user-defined series of actions in response. That’s why there is always an empty trigger in every new logic app by default.

Click the Add a trigger button, type HTTP request in the search box, and select When an HTTP request is received in the Request group of available triggers:

This will insert the selected trigger into the empty slot and open a group of settings. The two things you need here are the HTTP URL and the request body JSON schema:

To get the HTTP URL, you need to click Publish at the top. After that, you’ll see the auto-generated URL you can copy and paste elsewhere:

You can test this endpoint URL with curl:

curl -X POST 'INSERT_URL_HERE'`

When you open Run history in Development tools, you should see the timestamps for every time the trigger worked (because, so far, we only have the trigger in the project):

For the JSON schema in the trigger settings, use this code:

{
  "type": "object",
  "properties": {
    "Id": {
      "type": "string"
    },
    "Topic": {
      "type": "string"
    },
    "CreatedAt": {
      "type": "integer"
    },
    "Actor": {
      "type": "object",
      "properties": {
        "Type": {
          "type": "string"
        },
        "Id": {
          "type": "string"
        }
      }
    },
    "Data": {
      "type": "object",
      "properties": {
        "Path": {
          "type": "string"
        },
        "Size": {
          "type": "integer"
        }
      }
    }
  }
}

Step 2. Create the webhook

Now, let’s create a webhook that will trigger the app.

Log in to your SFTP To Go account and go to the Automation page. Click the + Add automation button.

Give the automation a meaningful name:

Keep the default trigger type (On a file or folder event) and select File created as the event type below:

We need the webhook to execute only when files are created in a specific folder. New files in other folders and new folders in the folder of interest should be ignored. Click + Add filter rule twice to set two rules:

  • Set the first rule to Path - starts with - <username>/inbound/.
  • Set the second rule to Type - is - File.

Replace <username> with the username from the credentials you will be using:

Now click + Add action and select Send webhook request in the list of available actions:

In your Logic App, copy the autogenerated HTTP URL to the clipboard and paste it into the Endpoint URL input box in the webhook settings dialog. Keep the rest of the settings at defaults:

Click Save automation to finalize.

SFTP To Go will offer to save the webhook secret that helps verify that incoming requests actually originated from the service and haven't been tampered with. You don’t need the secret to get the basics working. For now, save it somewhere safe and continue:

Step 3. Set up SFTP connection and get file content

Let’s get back to the Azure Logic App designer. The next step is to get the file content. Click the + button below the trigger and select Add an action in the drop-down list, then search for Get file content using path and select the respective action in the SFTP-SSH group:

This will first open a task panel to enter details for a new SFTP connection. At the bare minimum, submit the connection name, host server address, username, and password. You will find all this information on the Credentials page of your SFTP To Go dashboard:

Better yet, use your SSH private key for more secure authentication (and if you don’t, tick the Disable SSH host key validation? checkbox). Click Create new to create the connection.

Now you need to tell the action to take the full path to the newly created file from the JSON payload that the webhook submitted.

Click in the File entry box and then the fx button to open the expression editor.

Insert the following code:

concat('/', join(skip(split(uriComponentToString(replace(triggerBody()?['Data']?['Path'], '+', ' ')), '/'), 1), '/'))

Here is what’s going on here. We need the Get file content using path action to extract the full path to the file from the payload that the webhook submitted to our Logic App. The path is inside the Path child element of the Data element.

However, the payload will include the username in the path, and the SFTP-SSH action doesn’t need that: it already looks inside the folder that matches the username. So we use concat to ensure the path starts with a forward slash, and we use skip to remove the prepended username that is the first part of the path:

Click Add to finish inserting the expression. Your Logic App will now read the path to newly created files in the designated folder on your SFTP To Go account.

The next step is to access the file metadata that contains the modification timestamp. The reason we are doing this is that the payload's CreatedAt value records when SFTP To Go generated the event, and SFTP To Go doesn't document it as the file's modification time.

Add the Get file metadata using path action from the SFTP-SSH group right below the Get file content using path action, and use the same expression as above to access the newly uploaded file on SFTP To Go:

Step 4. Compose the new file name

We now need to compose a new file name that will consist of the original filename and the modification timestamp. Click + below the Get file metadata using path action, choose Add an action, search for the Compose action in the Data Operations group, and add it.

Let’s insert this code into the Inputs entry box as a function:

concat(substring(last(split(triggerBody()?['Data']?['Path'], '/')), 0, lastIndexOf(last(split(triggerBody()?['Data']?['Path'], '/')), '.')), '_', formatDateTime(body('Get_file_metadata_using_path')?['LastModified'], 'yyyyMMddTHHmmss'), substring(last(split(triggerBody()?['Data']?['Path'], '/')), lastIndexOf(last(split(triggerBody()?['Data']?['Path'], '/')), '.')))

The expression builds a new filename by inserting the file's modstamp between its base name and its extension. It first takes the trigger's Path value, splits it on /, and keeps the last segment (e.g., invoice.pdf). It then uses lastIndexOf to find the final . in that name, takes everything before it as the base name (invoice) and everything from the dot onward as the extension (.pdf).

In between, it adds an underscore and the LastModified value from the Get file metadata using path action, formatted as yyyyMMddTHHmmss. concat joins the pieces, so username/inbound/invoice.pdf modified at 13:02:26 on Oct 4, 2026 becomes invoice_20261004T130226.pdf:

Step 5. Create a new file on SFTP To Go

Next, let’s create a new file that is a copy of the file in question and uses the name that the app has just composed.

Add the Create file action from the SFTP-SSH group below Compose and set the output folder path: either type it in the Folder path entry box or click the Open folder button and select it in the browser:

Next, we need to inherit the composed new filename from the previous action. To do that, click the File name entry box and then the fx button to open the expression editor. In the editor, switch to Dynamic content, select Outputs under Compose, and then click Add to add the expression:

For File content, repeat the last step, but choose File content from the Get file content using path action and click Add:

SFTP file management in Azure Logic Apps

The basic workflow is ready: the Logic App should get triggered every time you upload a new file to the inbound folder, read the file, extract its base name and modstamp, construct a new filename, and save a copy of the file with that name to a designated folder. Click Publish at the top, and let’s test it.

Upload a file to inbound:

Check the outbound folder for the file:


Possible safeguards and improvements

The simple Logic App we created has a fairly straightforward linear sequence of actions, mainly from the SFTP - SSH connector, one HTTP request trigger, and one action from the Data operations group. 

When you start building various safeguards around possible failures, the logic can become more complex. For example, if you add a Delete file action to remove the original file from inbound once you’ve made a copy with a modstamp in the name, you may want to protect yourself against copying and deleting ongoing (and thus partial) uploads:

The app waits 30 seconds, then compares the file's current size with the size from the webhook. Processing continues only if they match. This doesn’t eliminate potential issues, but it reduces the risk.

As you can see from these example workflows, the designer’s boxes, arrows, and the branches a condition draws carry the flow, but the actual logic often lives in a handful of expressions.


Wrapping up

Connecting Azure Logic Apps to SFTP To Go often boils down to just a few building blocks: a trigger that listens to incoming HTTP requests and actions that connect to the service over SFTP to get a new file and its metadata.

The example in this guide is intentionally simple, but the same shape scales to heavier integrations. You could be parsing trading partner files, validating payloads, or routing to Azure Storage or Service Bus instead of another SFTP folder.

The core flow may grow with complexity, but so can all the error handling that needs to account for incomplete uploads, failing actions, and so many more things.

Ready to try building something more complex yourself? Start a free 7-day SFTP To Go trial and connect your first Logic App in minutes. A credit card’s not required.

Explore SFTP To Go's native file automations or, learn how SFTP To Go is addressing post quantum threats.


Frequently Asked Questions

The folder picker in the SFTP-SSH connector doesn’t display folders I created after establishing the initial connection. How do I fix that?

Indeed, the Logic App designer caches the directory structure when the SFTP connection is initially established. It doesn’t automatically refresh the list of folders in real time when new folders are created.

The easiest way to work around this limitation is to just type the folder path manually. If you already know the name of the folder and the path to it on the SFTP server, you don’t need the folder picker. Just type or paste the path (e.g., /your-new-folder) directly into the Folder path entry box.

Can I reuse the same SFTP connection in multiple Logic Apps?

Yes. When you create an SFTP-SSH connection inside a Logic App on the Consumption tier, Azure creates it as a standalone API connection resource inside your resource group. Every new Logic App you create in that resource group then automatically uses that connection when it needs to connect to an SFTP server.

On Logic Apps Standard, though, connections work differently and are usually managed via app settings or Azure Key Vault instead.

Why does the Get file content action fail with File not found even though the file is clearly on the server?

This largely depends on how you trigger your Logic App.

When you use the SFTP-SSH’s trigger that monitors an SFTP folder for new content, a likely reason is that an expression is pointing to the wrong metadata field, for example, triggerBody()?[‘Name’] (just the filename) instead of triggerBody()?[‘Path’] (the full path). The error message is typically the giveaway: if it names just the filename with no folder in front of it, check every expression in the faulty action and confirm it references Path, not Name.

Another possibility is that something else renamed or deleted the file on the server right after the file was listed or copied.

With webhooks, the most likely reason is that SFTP To Go gives you a full path to the file while the SFTP-SSH connector expects a relative path. In that case, you’ll need to fiddle with concat and replace a bit. Please see an example of their use above.

In the extended example of this Logic App, you mentioned a 30-second delay to check whether the upload is complete or partial. My files take longer than 30 seconds to upload. Where do I adjust that, and is there a better way to deal with this than a fixed delay?

You need to increase the Delay action’s duration to exceed your slowest expected upload time, or replace the single delay-and-check with an Until loop that keeps re-checking file size every few seconds up to a maximum number of attempts.

That said, the loop version is more robust for variable upload times, because it doesn’t force you to guess one fixed delay that works for every file.

Should I authenticate with a user/password pair or with an SSH private key and its passphrase?

Either works with the SFTP-SSH connector, but a key-based connection is generally the more secure option for production, and it’s easier to rotate without touching every Logic App that references the shared connection.

I think I did everything right, but I’m getting junk folders instead of new files with modstamps in the output folder.

The likely reason is that you inserted the expression that starts with concat into the Compose inputs as literal text. Copy that expression to the clipboard, delete everything, click inside the entry box, then click on the fx icon, and insert the clipboard contents as an expression, then click Update.

I’m not going to be fetching files from the home folder of the user I created to get access to files. It’s going to be a whole different folder like marketing. Should I adjust the concat expression accordingly?

You can, but it may be a better idea to use virtual folders. Please see the documentation that covers the steps to do so and the best practices.

I can’t make sense of drafts and published versions. How do I control which revision I deploy?

In the preview designer, everything you edit is saved to a draft. The published version, the one marked Active, runs in production and doesn't change until you click Publish.

Which version runs depends on how it starts:

  • Run draft (the button at the bottom of the designer) runs the draft. These runs are tagged Draft in Run history.
  • Real requests run the published version, including SFTP To Go webhooks and curl calls to the trigger URL.

So, build and test with Run draft (and a sample payload where available, since a bare run sends an empty body and triggerBody()?['Data']?['Path'] will be null), then click Publish before relying on the webhook.