SFTP Integration
SFTP (Secure File Transfer Protocol) is the channel through which QI CTVM makes fund reports available for download. The available models, the column-by-column layout of each file, and downloadable examples are in the DTVM Reports documentation.
For the integration, we recommend libraries and clients that implement the protocol, such as paramiko in Python, the command-line sftp, or any standard SFTP client.
To request access, contact integracao.dtvm@qitech.com.br. Access is granted first in the Sandbox environment and then in Production.
How authentication works
Access is authenticated with an SSH public key — there is no password. You generate the key pair, keep the private key under your control, and send us only the public key, which we register on your SFTP user.
| Who | What they provide |
|---|---|
| You | The public key (the .pub file), in OpenSSH format |
| QI CTVM | HOSTNAME, PORT (22) and USERNAME, plus the host fingerprint |
No QI Tech team will ever ask for your private key. If someone asks — by e-mail, by ticket, or through any other channel — it is not us. The 1Password sharing described in step 3 is for the public key (sftp_qitech.pub) only.
If the private key has already been sent to anyone or attached anywhere, treat it as compromised: generate a new pair and send us the new public key.
1. Generating the key pair
Generate a pair dedicated to SFTP. Do not reuse the key that signs your JWT tokens: they are credentials for different systems, with different life cycles — rotating one would force rotating the other, and a leak on either side would affect both.
Replace company-name with your company's name — for example, sftp-acme. This text is only a comment inside the key, and it is there to help us identify it.
- Linux / macOS
- Windows (PowerShell)
- Windows (cmd)
- Windows (WSL)
mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keygen -t ed25519 -C "sftp-company-name" -f ~/.ssh/sftp_qitech
New-Item -ItemType Directory -Force "$env:USERPROFILE\.ssh" | Out-Null
ssh-keygen -t ed25519 -C "sftp-company-name" -f "$env:USERPROFILE\.ssh\sftp_qitech"
if not exist "%USERPROFILE%\.ssh" mkdir "%USERPROFILE%\.ssh"
ssh-keygen -t ed25519 -C "sftp-company-name" -f "%USERPROFILE%\.ssh\sftp_qitech"
mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keygen -t ed25519 -C "sftp-company-name" -f ~/.ssh/sftp_qitech
Inside WSL, use the Linux path (~/.ssh). The key is stored in the WSL file system, not in the Windows user folder.
Each tab writes the folder path the way that particular program understands it, so the commands are not interchangeable. If you run the command from one tab in a different program, you get No such file or directory and no key is created — just go back and copy the command from the right tab.
On Windows, if you are not sure which one to use, use PowerShell: it is what Windows Terminal opens by default.
The command asks for a passphrase and generates two files:
| File | What it is |
|---|---|
sftp_qitech | Private key. Never send it, never share it. |
sftp_qitech.pub | Public key. This is the one you must send us. |
About the passphrase:
- Automated integration (a service of yours downloading the reports): leave it empty, pressing Enter at both prompts, and protect the private key wherever it is stored, in a secrets manager with restricted access. A passphrase that has to be available to the process at run time adds no real protection.
- Use by a person: set a passphrase.
ssh-keygen already creates the private key with permissions restricted to your user. If you copy the file to another machine, restore the permissions — SSH clients refuse private keys that are readable by other users:
chmod 600 ~/.ssh/sftp_qitech
2. Checking the public key format
The content of the .pub file is a single line, starting with the key type and ending with the comment:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE1wA3uBEFYG+Yi7zIw7/YUJJ4fBB0MUZsvUVaqyyv6M sftp-acme
Check the file before sending it to us:
ssh-keygen -lf ~/.ssh/sftp_qitech.pub
The expected response is the key fingerprint, in the format 256 SHA256:... sftp-acme (ED25519). If the command answers is not a public key file, the file is corrupted or is not an OpenSSH public key.
If your key is in PEM/X.509 format
A key that starts with -----BEGIN PUBLIC KEY----- is in PEM/X.509 format, the OpenSSL standard. That format cannot be registered on the SFTP: the server expects the OpenSSH format, on a single line.
If that key is already dedicated to SFTP, you do not need to generate another one — just convert it:
-
You still have the matching private key. Works for any key type:
ssh-keygen -y -f path/to/private_key -
You only have the public key in PEM. Works for RSA keys:
ssh-keygen -i -m PKCS8 -f path/to/public_key.pem
Both commands print the key in OpenSSH format to standard output. The conversion does not preserve the original comment; if you want, append sftp-company-name to the end of the line.
3. Sending the public key
Send the public key through 1Password, sharing the item with the integration team. This is the channel we use to receive keys: it preserves the content exactly as you generated it and keeps the origin of the delivery verifiable — anyone able to replace your public key along the way would gain access to your SFTP directory.
- In 1Password, create an item and paste the content of the
sftp_qitech.pubfile into it as plain text, on a single line, with no line breaks. - Add the key fingerprint — the output of the
ssh-keygen -lffrom the previous step. We compare it with the fingerprint of the key we received and confirm it was not altered along the way. - Share the item with the integration team and let us know at integracao.dtvm@qitech.com.br that the item has been shared.
.docx or .pdfThe automatic formatting of those programs replaces characters (a + with an em dash, straight quotes with typographic ones) and inserts line breaks. Any of those changes invalidates the key, and the error only shows up at connection time.
Once the public key is registered, we confirm the release and send you the HOSTNAME, the USERNAME, and the host fingerprint.
4. Connecting to the SFTP
Check the host key on the first connection
On the first connection, your client will ask whether you trust the server. Do not accept it without checking: compare the fingerprint shown with the one the integration team sent. That comparison is what prevents another server from impersonating ours.
ssh-keyscan -t ed25519 <hostname> > qitech_host_key
ssh-keygen -lf qitech_host_key # compare with the fingerprint sent by QI CTVM
cat qitech_host_key >> ~/.ssh/known_hosts
Once checked, known_hosts becomes the client's reference, and connections presenting a different host key are refused automatically.
Connection credentials
| Credential | Source |
|---|---|
HOSTNAME | Server address, provided by QI CTVM |
PORT | 22 |
USERNAME | User, provided by QI CTVM |
| Private key | The sftp_qitech file you generated |
These credentials provide direct access to your fund's reports and should not be shared.
Code example
- Python
import paramiko
HOSTNAME = "sftp.example.com" # provided by QI CTVM
PORT = 22
USERNAME = "username" # provided by QI CTVM
PRIVATE_KEY = "/path/to/sftp_qitech" # the private key you generated
KNOWN_HOSTS = "/path/to/known_hosts" # with the QI CTVM host key already checked
client = paramiko.SSHClient()
client.load_host_keys(KNOWN_HOSTS)
# Refuses the connection if the host key is not the expected one.
# Do not use AutoAddPolicy: it accepts any server with no verification.
client.set_missing_host_key_policy(paramiko.RejectPolicy())
client.connect(
hostname=HOSTNAME,
port=PORT,
username=USERNAME,
key_filename=PRIVATE_KEY, # paramiko identifies the key type from the file
look_for_keys=False,
allow_agent=False,
timeout=30,
)
try:
with client.open_sftp() as sftp:
# Lists the available files
for name in sftp.listdir("/"):
print(name)
# Downloads a file
sftp.get("remote/path/file.csv", "local/path/file.csv")
finally:
client.close()
5. Downloading the files
Files are named from the fund short name, the report model and the reference date in YYYY-MM-DD format:
example_name_assets_wallet_composition_2026-07-29.csv
The available models, the column-by-column layout of each file, and downloadable examples are in the DTVM Reports documentation.
The SFTP service provided is exclusively for downloading files; upload is not permitted.
Key rotation and revocation
To replace the key, generate a new pair and send us the new public key through 1Password, following steps 1 to 3. We register the new key and let you know when the previous one has been removed, so the switch happens with no downtime window.
If you suspect the private key has been compromised, notify the integration team at the same contact: we revoke the old key's access immediately, before registering the new one.