> ## Documentation Index
> Fetch the complete documentation index at: https://agents.nanonets.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# FTP Upload

> Agent tool that delivers a platform file to a folder on a connected FTP or FTPS server.

This document covers `export_to_ftp` (display name **"FTP Upload"**), the agent tool that delivers a platform file to a folder on a connected FTP or FTPS server. It is the FTP counterpart of [SFTP Upload](/docs/tools/export-to-sftp): same inputs, same upload mechanics, same result shape. Use it when the customer's server speaks FTP (port 21, or 990 for implicit TLS) rather than SFTP over SSH (port 22).

## Authentication and enablement

The tool uses a workspace **FTP / FTPS** integration (`integrations.service_name = 'ftp'`). The hidden `integration_id` is resolved from the configured tool binding with `first_active`; credentials are loaded in the worker only after verifying that the integration belongs to the task workspace and is active.

The integration holds host, username, password, the folder the connection may write to, an optional port (empty means the standard port for the chosen mode: 21, or 990 for implicit TLS), and two security settings:

* **Connection security** — `ftps_explicit` (default: the standard port is upgraded with `AUTH TLS`), `ftps_implicit` (TLS from the first byte, usually port 990), or `plain` (unencrypted FTP; passwords and files travel in clear text, so use it only for a server that cannot do TLS).
* **Certificate verification** — trusted certificate authorities (default), or pin the server certificate on first connection. Pinning is for self-signed certificates: the SHA256 fingerprint is recorded when the integration is saved and any other certificate is refused afterwards, the same trust-on-first-use the SFTP integration applies to host keys.

Saving the integration connects, logs in and enters the folder, so a wrong password or an unreachable server is reported at setup time. Connections are always passive mode: the server must allow inbound connections on its passive data-port range as well as the control port. Off by default — enable it in the agent's Tools panel. It is billed at the same per-call rate as SFTP Upload.

## Inputs

Required:

* `file_url`: URL of the source file in platform storage, or from a tool such as `generate_file`, `python_code`, or another file-producing tool.
* `file_name`: Destination filename including its extension, for example `invoice-1722000000.edi`. It must be a single filename, not a path.

Optional:

* `folder_path`: Folder beneath the integration's configured folder, for example `qa/reports`. Missing folders are created automatically. Omitted means the configured folder.
* `conflict_behavior`:
  * `replace` (default): converge on one destination path. The temporary file is renamed over the existing one. A server that refuses to rename over an existing file gets a three-step fallback: the existing file is moved aside under a hidden name, the new file is renamed into place, and the aside copy is removed. The previous file is never deleted before the new one is in place; if the final rename fails it is moved back and the call reports the failure. The gap between the two renames is a brief moment with no file under the final name (SFTP's rename is atomic; FTP's is up to the server).
  * `rename`: preserve the existing file and choose `name (1).ext`, `name (2).ext`, and so on.
  * `fail`: return an error without changing the existing file.

Absolute paths, `..` traversal, sibling-prefix escapes, separators in `file_name`, and NUL bytes are rejected before upload.

## Upload mechanics

1. Download the complete source through the platform file-storage service.
2. Resolve the destination beneath the connection's absolute folder.
3. Write a unique hidden temporary sibling such as `.report.csv.part-<uuid>`.
4. Rename it into the final destination.
5. Check the final file's size against the bytes sent.

Temporary files are removed on handled failures. A worker or server crash can leave an orphaned `.part-*` file, but it cannot expose a partial file under the requested final name.

## Size and retry behavior

The maximum source size is **500 MB**, matching platform file storage. The current implementation downloads and uploads the content from worker memory.

The default `replace` behavior is retry-friendly: repeating the same call converges on the same path and content. `rename` intentionally creates another uniquely named file on a retry. If exactly-once delivery matters, use a deterministic filename with `replace`, or make the receiving system idempotent.

## Output

The structured result contains:

* `tool_name`
* the final `file_name` (including any conflict suffix)
* requested `folder_path`
* `file_size`
* applied `conflict_behavior`
* `completed_at`

FTP does not provide a public file URL, so the tool returns destination metadata rather than a link.

## Auditing and errors

Connect, stat, create-folder, put, rename, and cleanup operations emit host-only `external_call` audit events under `ProviderFtp`. Audit events do not include remote paths, file names, credentials, or file contents. A plain-FTP integration is also logged as such when it is validated.

Common failures include:

* missing or expired source `file_url`
* invalid destination path or filename
* inactive or cross-workspace integration
* `FTP certificate fingerprint is missing; reconnect the integration` — pinning is selected but no fingerprint was recorded
* `failed to connect to FTP server` — the server is unreachable from the platform's egress address, refused the login, or presented a certificate that does not match the pin
* `commit uploaded file: … previous file kept` — the server refused to rename the new file into place even after the existing one was moved aside; the previous file is back under its name, and the account usually lacks rename permission on the folder
