Transfer History & CSV Export
Review completed transfers and export the history as CSV.
For auditing and reporting, this example looks up the summary and per-file results of a completed transfer and exports the full history to a CSV file.
Steps
- Log in and take a completed transfer's
monitorId. - Fetch the summary with
GET /api/transfer-history/{id}/detail. - Fetch per-file results with
.../get-files. - Export the history with
GET /api/transfer-history/export-csv.
Configuration
Set your credentials and IDs via environment variables or a .env file (INNORIX_BASE_URL, INNORIX_WORKSPACE_ID, INNORIX_EMAIL, INNORIX_PASSWORD, and the INNORIX_SOURCE_ID / INNORIX_TARGET_ID / path variables the example uses).
API
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/transfer-history/{id}/detail | Get a completed transfer's summary |
| GET | /api/transfer-history/{id}/get-files | Get per-file results |
| GET | /api/transfer-history/export-csv | Export transfer history as CSV |
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""
09 - Transfer history & CSV report
=================================
Look up the detail and per-file results of a completed transfer, and export the
whole history as CSV for auditing/reporting.
This file is self-contained: it embeds a minimal client so it can be read and
run on its own.
Endpoints:
GET /api/transfer-history/{id}/detail?idType=monitor
GET /api/transfer-history/{id}/get-files?idType=monitor
GET /api/transfer-history/export-csv
Run:
MONITOR_ID=<monitor_id> python 09_transfer_history.py
"""
from __future__ import annotations
import os
import json
import logging
import requests
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass
# --------------------------------------------------------------------------- #
# Configuration
# --------------------------------------------------------------------------- #
BASE_URL = os.getenv("INNORIX_BASE_URL", "https://app.innorix.com")
WORKSPACE_ID = os.getenv("INNORIX_WORKSPACE_ID", "<WORKSPACE_ID>")
EMAIL = os.getenv("INNORIX_EMAIL", "<YOUR_EMAIL>")
PASSWORD = os.getenv("INNORIX_PASSWORD", "<YOUR_PASSWORD>")
MONITOR_ID = os.getenv("MONITOR_ID", "<MONITOR_ID>")
logging.basicConfig(level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%H:%M:%S")
log = logging.getLogger("innorix")
# --------------------------------------------------------------------------- #
# Minimal client
# --------------------------------------------------------------------------- #
class ApiError(RuntimeError):
"""Raised when the API returns a non-2xx response."""
class InnorixClient:
def __init__(self, base_url: str, workspace_id: str, timeout: float = 15.0):
self.base_url = base_url.rstrip("/")
self.workspace_id = workspace_id
self.timeout = timeout
self.session = requests.Session()
def _request(self, method: str, path: str, **kwargs):
kwargs.setdefault("timeout", self.timeout)
res = self.session.request(method, f"{self.base_url}{path}", **kwargs)
try:
res.raise_for_status()
except requests.HTTPError as exc:
raise ApiError(f"{method} {path} -> {res.status_code}: {res.text[:500]}") from exc
if not res.content:
return None
try:
return res.json()
except ValueError:
return res.text # e.g. CSV export
def login(self, email: str, password: str) -> str:
data = self._request("POST", "/api/auth/login",
json={"email": email, "password": password}, timeout=10)
token = data["data"]["user"]["accessToken"]
self.session.headers.update({
"Authorization": f"Bearer {token}",
"x-workspace-id": self.workspace_id,
"Content-Type": "application/json",
})
log.info("logged in")
return token
def history_detail(self, monitor_id: str, id_type: str = "monitor"):
return self._request("GET", f"/api/transfer-history/{monitor_id}/detail",
params={"idType": id_type}, timeout=10)
def history_files(self, monitor_id: str, id_type: str = "monitor",
page: int = 1, size: int = 20):
return self._request("GET", f"/api/transfer-history/{monitor_id}/get-files",
params={"idType": id_type, "page": page, "size": size}, timeout=10)
def export_history_csv(self, out_path: str, page: int = 1, size: int = 50, sort=None) -> str:
params = {"page": page, "size": size}
if sort:
params["sort"] = sort
text = self._request("GET", "/api/transfer-history/export-csv", params=params, timeout=30)
with open(out_path, "w", encoding="utf-8", newline="") as fh:
fh.write(text if isinstance(text, str) else json.dumps(text))
log.info("history CSV saved to %s", out_path)
return out_path
# --------------------------------------------------------------------------- #
# Run
# --------------------------------------------------------------------------- #
def main() -> None:
client = InnorixClient(BASE_URL, WORKSPACE_ID)
client.login(EMAIL, PASSWORD)
# Summary of a completed transfer (idType=monitor because we pass a monitorId).
detail = client.history_detail(MONITOR_ID, id_type="monitor")
print(json.dumps(detail, indent=2, ensure_ascii=False)[:1000])
# Per-file results.
files = client.history_files(MONITOR_ID, id_type="monitor", page=1, size=20)
print(json.dumps(files, indent=2, ensure_ascii=False)[:1000])
# Export history as CSV.
out = client.export_history_csv("transfer_history.csv", page=1, size=50, sort="createdAt:desc")
print("saved:", out)
if __name__ == "__main__":
main()