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

# SFTP setup

> Deliver mapping result files to any SFTP server using password authentication or SSH public-key authentication.

An SFTP delivery destination uploads a result file to your server every time a mapping job completes. You can authenticate with a password or with SSH public-key auth — the latter is recommended for production.

## Authentication methods

<CardGroup cols={2}>
  <Card title="Password auth" icon="lock">
    Simpler to configure. Use for internal servers or quick testing. Store the password as a secret in the destination config.
  </Card>

  <Card title="SSH key auth" icon="key">
    Recommended for production. Mapping.Travel generates a persistent per-org key pair. You add the public key to your server's `authorized_keys`.
  </Card>
</CardGroup>

***

## Password authentication

### Create via API

```bash theme={null} theme={null}
curl -X POST https://api.mapping.travel/api/v1/delivery-destinations \
  -H "X-API-Key: <your-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "SFTP",
    "name": "Partner SFTP (password)",
    "sftp": {
      "host": "sftp.partner.example.com",
      "port": 22,
      "username": "mapping-travel",
      "password": "s3cr3t",
      "remotePath": "/incoming/mapping-results/",
      "hostFingerprints": ["SHA256:abc123…"]
    },
    "status": "ACTIVE"
  }'
```

<Warning>
  Always supply `hostFingerprints` in production. Without them, the connection is not protected against host key substitution attacks. See [Capturing host fingerprints](#capturing-host-fingerprints) below.
</Warning>

***

## SSH public-key authentication

### Step 1 — Fetch your org's public key

Each organization has a single persistent SSH key pair managed by Mapping.Travel. The public key is generated the first time you request it (idempotent on subsequent requests):

```bash theme={null} theme={null}
curl https://api.mapping.travel/api/v1/delivery-destinations/sftp/public-key \
  -H "X-API-Key: <your-token>"
```

Response:

```json theme={null} theme={null}
{
  "publicKey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI… mapping-travel-org_01HZ"
}
```

The key type is **Ed25519**. The comment at the end (`mapping-travel-org_…`) identifies your organization.

### Step 2 — Authorize the key on your SFTP server

Append the public key to `~/.ssh/authorized_keys` for the SFTP user:

```bash theme={null} theme={null}
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI… mapping-travel-org_01HZ" \
  >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
```

If you use a managed SFTP service (AWS Transfer Family, SFTP Gateway, etc.), paste the public key in that service's key management UI instead of editing `authorized_keys` directly.

### Step 3 — Capture host fingerprints

Before creating the destination, collect the server's host fingerprints so Mapping.Travel can perform strict host checking:

```bash theme={null} theme={null}
ssh-keyscan -t ed25519 sftp.partner.example.com
```

This outputs a line like:

```
sftp.partner.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI…
```

Hash it to get the SHA-256 fingerprint Mapping.Travel expects:

```bash theme={null} theme={null}
ssh-keyscan -t ed25519 sftp.partner.example.com \
  | ssh-keygen -lf - \
  | awk '{print $2}'
# SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

### Step 4 — Create the destination

```bash theme={null} theme={null}
curl -X POST https://api.mapping.travel/api/v1/delivery-destinations \
  -H "X-API-Key: <your-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "SFTP",
    "name": "Partner SFTP (SSH key)",
    "sftp": {
      "host": "sftp.partner.example.com",
      "port": 22,
      "username": "mapping-travel",
      "authMethod": "PUBLIC_KEY",
      "remotePath": "/incoming/mapping-results/",
      "hostFingerprints": ["SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
    },
    "status": "ACTIVE"
  }'
```

Note: when `authMethod` is `"PUBLIC_KEY"`, omit `password` — the org key pair is used automatically.

***

## Capturing host fingerprints

Host fingerprints protect against man-in-the-middle attacks. You should supply at least one fingerprint for every destination.

```bash theme={null} theme={null}
# Collect the fingerprint from the server you trust
ssh-keyscan -t ed25519,rsa sftp.partner.example.com \
  | ssh-keygen -lf - \
  | awk '{print $2}'
```

Pass each fingerprint as a string in the `hostFingerprints` array. If the server presents a key that does not match any of the configured fingerprints, the delivery fails with `HOST_KEY_MISMATCH` and is not retried until you update the config.

***

## Remote path conventions

The `remotePath` field sets the directory on the SFTP server where files are written. The SFTP user must have write permission to this directory.

| `remotePath`                    | File written at                                                        |
| ------------------------------- | ---------------------------------------------------------------------- |
| `/incoming/`                    | `/incoming/mapping_results_INV-1234_2026-06-07.csv`                    |
| `/home/mapping-travel/exports/` | `/home/mapping-travel/exports/mapping_results_INV-1234_2026-06-07.csv` |

See [File format](/delivery-destinations/file-format) for the full file naming pattern.

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Authentication failed — wrong credentials or key not authorized">
    For password auth: verify the username and password are correct. The SFTP user must have shell or SFTP-subsystem access.

    For SSH-key auth: confirm the exact public key returned by `GET /api/v1/delivery-destinations/sftp/public-key` is present in `~/.ssh/authorized_keys` on a single line with no line breaks. Run the [connection test](/delivery-destinations/testing) and check `error` for the server's rejection message.
  </Accordion>

  <Accordion title="HOST_KEY_MISMATCH — fingerprint doesn't match">
    The server's current host key does not match any fingerprint in `hostFingerprints`. This can mean:

    * You copied the fingerprint incorrectly. Re-run `ssh-keyscan` and compare.
    * The server rotated its host key (e.g. after a rebuild). Update the destination with the new fingerprint.
    * A genuine host key substitution attack. Investigate before updating.
  </Accordion>

  <Accordion title="No such file or directory — remote path missing">
    The `remotePath` directory must exist before Mapping.Travel attempts delivery. Create it on the SFTP server:

    ```bash theme={null} theme={null}
    mkdir -p /incoming/mapping-results/
    chown mapping-travel /incoming/mapping-results/
    ```
  </Accordion>

  <Accordion title="Connection timeout or refused">
    Verify the `host` and `port` are reachable from the public internet. If the SFTP server is behind a firewall, allow inbound connections from Mapping.Travel's egress IP range (contact support for the current list).
  </Accordion>
</AccordionGroup>
