Appearance
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
- Go to Data Sources → New Data Source
- Select SFTP
- Fill in the connection details:
| Field | Description |
|---|---|
| Name | How scripts reference this connection (e.g. VendorSftp) |
| Host | Hostname or IP of the SFTP server |
| Port | Defaults to 22 |
| Base Path | Optional base directory to scope all operations (e.g. /uploads). Scripts cannot navigate above this path. |
| Username | SFTP username |
| Password | Password authentication (stored encrypted). Leave blank if using a private key. |
| Private Key | PEM-format private key for key-based authentication (stored encrypted). |
| Passphrase | Passphrase for the private key, if it is encrypted. |
| Host Fingerprint | Expected server fingerprint (e.g. SHA256:abc123...). When set, connections are rejected if the server presents a different key — protects against MITM. |
- Click Test Connection to verify
- 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.
| Method | Description |
|---|---|
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')
}