Skip to content

SFTP

An SFTP data source connects ApiMeld to an SSH file transfer server. Scripts can list, read, upload, and manage files — subject to the permissions of the configured SFTP account — on any SFTP-accessible host including on-premises servers, cloud storage gateways, or hosted SFTP services.

Setting up an SFTP data source

  1. Go to Data SourcesNew Data Source
  2. Select SFTP
  3. Fill in the connection details:
FieldDescription
NameHow scripts reference this connection (e.g. VendorSftp)
HostHostname or IP of the SFTP server
PortDefaults to 22
Base PathOptional base directory to scope all operations (e.g. /uploads). Scripts cannot navigate above this path.
UsernameSFTP username
PasswordPassword authentication (stored encrypted). Leave blank if using a private key.
Private KeyPEM-format private key for key-based authentication (stored encrypted).
PassphrasePassphrase for the private key, if it is encrypted.
Host FingerprintExpected server fingerprint (e.g. SHA256:abc123...). When set, connections are rejected if the server presents a different key — protects against MITM.
  1. Click Test Connection to verify
  2. Save

Key-based authentication

Private key authentication is more secure than passwords for SFTP. Generate a key pair, add the public key to the server's authorized_keys, and paste the private key (PEM format) into ApiMeld. The private key is stored AES-256-GCM encrypted.

Host fingerprint

Set the Host Fingerprint for any production SFTP connection. You can get the fingerprint by running ssh-keyscan -t ed25519 your-sftp-host and noting the hash, or from your SFTP provider's documentation.

Available methods

All paths are relative to the configured Base Path. Write operations (Upload, DeleteFile, MoveFile, Mkdir, Rmdir) will fail if the configured credentials only have read access on the SFTP server — what ApiMeld can do is limited by the permissions granted to the SFTP account.

MethodDescription
List(path?, pattern?)List files and directories. Optional glob pattern (e.g. *.xml).
Exists(path)Returns true if the file or directory exists.
ReadRaw(path)Read file contents as a string.
ReadCsv(path, delimiter?)Parse a CSV file and return an array of row objects.
ReadExcel(path, sheet?)Parse an Excel file (.xlsx) and return an array of row objects.
TempPath(path)Download the file to a local temp path and return that path.
Upload(path, content)Write a string to a remote file (creates or overwrites).
DeleteFile(path)Delete a remote file.
MoveFile(sourcePath, destPath)Move or rename a file on the server.
Mkdir(path)Create a remote directory.
Rmdir(path)Remove a remote directory.

Upload vs WriteFile

SFTP uses Upload / upload where Network Share uses WriteFile / writeFile. Everything else is the same.

List() returns an array of objects with: name, isDirectory, sizeBytes, modifiedAt.

File reads are subject to a configurable size limit (default 25 MB). An admin can raise this under Admin → Settings → Storage.

PowerShell examples

powershell
# List all XML files waiting to be processed
$files = $datasources.VendorSftp.List("Incoming", "*.xml")
$logger.Info("Files waiting: $($files.Count)")

# Read a remote file as text
$content = $datasources.VendorSftp.ReadRaw("Incoming/orders.xml")

# Read a CSV from the SFTP server
$rows = $datasources.VendorSftp.ReadCsv("Exports/daily.csv")
$logger.Info("Rows received: $($rows.Count)")

# Upload a result file back to the server
$datasources.VendorSftp.Upload("Outgoing/processed.csv", "id,status`n1,ok`n2,ok")

# Download to a temp path for tools that need a real file path
$localPath = $datasources.VendorSftp.TempPath("Incoming/report.xlsx")
$data = Import-Excel -Path $localPath

# Archive after processing
$datasources.VendorSftp.MoveFile("Incoming/orders.xml", "Archive/orders.xml")

JavaScript / TypeScript examples

javascript
// List incoming files
const files = await datasources.VendorSftp.list('Incoming', '*.xml')
logger.info(`Files waiting: ${files.length}`)

// Read a remote CSV
const rows = await datasources.VendorSftp.readCsv('Exports/daily.csv')
logger.info(`Rows received: ${rows.length}`)

// Upload a result file
const output = rows.map(r => `${r.id},processed`).join('\n')
await datasources.VendorSftp.upload('Outgoing/results.csv', `id,status\n${output}`)

// Archive the source file
await datasources.VendorSftp.moveFile('Exports/daily.csv', 'Archive/daily.csv')

Common patterns

Download, process, and acknowledge

powershell
$files = $datasources.VendorSftp.List("Incoming", "*.csv")

foreach ($f in $files) {
    $rows = $datasources.VendorSftp.ReadCsv("Incoming/$($f.name)")

    # Process rows — insert into DB, call an API, etc.
    foreach ($row in $rows) {
        # ...
    }

    # Write an acknowledgement file and archive the source
    $datasources.VendorSftp.Upload("Ack/$($f.name).ack", "processed")
    $datasources.VendorSftp.MoveFile("Incoming/$($f.name)", "Archive/$($f.name)")
    $logger.Info("Processed: $($f.name)")
}

Only process if file exists

javascript
const path = 'Incoming/nightly-export.csv'

if (await datasources.VendorSftp.exists(path)) {
  const rows = await datasources.VendorSftp.readCsv(path)
  logger.info(`Processing ${rows.length} rows`)
  await datasources.VendorSftp.moveFile(path, `Archive/nightly-export.csv`)
} else {
  logger.warn('Nightly export not yet available — will retry next run')
}