Getting Started
Core Concepts
Run file transfer functions from an application
File-processing work in an application consists of preparing files, requesting a transfer, and then proceeding with the next task based on the processing result.
Application integration connects file transfer functions to application requests so that transfers can run when needed and their results can be used in the application's business logic.
Application
│
│ Transfer Request
▼
File Transfer
│
├── File Processing
├── Progress
└── Result
│
▼
Application Logic

This connects file transfer and result processing to the application's business functions.
Integration Flow
Connect the entire flow from transfer request to result processing
When an application generates a file transfer request, execute the task based on the files to transfer and the destination information.
Use transfer progress and response information in the application, then continue the next business logic according to the final result.
File Transfer Request
│
▼
Configure File and Destination Information
│
▼
Execute Transfer Task
│
▼
Receive Status and Response Information
│
▼
Confirm Final Result
│
▼
Process Application Logic
Connecting file transfer and result processing around a single request lets completed tasks flow naturally into the next business operation.
Development Benefits
Apply file transfer functions to an application's business workflow
Application integration connects the execution process and result handling required for file transfer to service functions.
| Category | Application Integration |
|---|---|
| Transfer Execution | Start file transfers based on application requests |
| Status Usage | Connect progress status and response information to screens and business logic |
| Result Processing | Use the final result in the next business function |
| Business Extension | Connect storage, processing, notifications, and other next steps after transfer completion |
This configuration lets you use file transfer from the initial request through result processing in line with the application's business workflow.
IT Engineers
Build and manage application file transfer integration
Integration Setup
Connect the application to the file transfer environment
First, configure the file transfer environment and integration method so the application can use file transfer functions.
Configure request and response paths so application requests are connected to file transfer tasks and execution status and result information can be returned.
┌─────────────────┐
│ Application │
└────────┬────────┘
│
│ Request / Response
▼
┌─────────────────┐
│ Transfer Layer │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Transfer Device │
└─────────────────┘

This integration environment connects the application's business functions to actual file transfer tasks.
Request Configuration
Define the files, destination, and execution conditions for the transfer
Configure which request from the integrated application should trigger a file transfer.
A request can include the files to transfer, file paths, destination location, and conditions required for execution.
Transfer Request
│
├── Source
│ └── File / Path
│
├── Target
│ └── Device / Workspace
│
└── Options
│
▼
Transfer Run

| Configuration Item | Setting |
|---|---|
| Source | Files or file paths to transfer |
| Target | Device or workspace to which files are transferred |
| Request | Request information supplied by the application |
| Options | Execution conditions applied to file processing |
| Flow | File transfer task executed for the request |
Once the request structure is configured, the required file transfer can run according to the application's business conditions.
Response Handling
Connect transfer status and response results to application logic
When a file transfer runs, status and response information are generated as it starts, progresses, and completes.
Connecting this information to the application's screens and business logic lets you display current progress and configure processing flows for each result.
Transfer Run
│
├── Started
│
├── Progress
│
└── Result
│
┌────┼────┐
▼ ▼ ▼
Success Retry Error
│ │ │
▼ ▼ ▼
Next Retry Result
Logic Run Handling

| Transfer Information | Application Usage |
|---|---|
| Started | Display the transfer start status |
| Progress | Display progress and processing status |
| Success | Run the next business logic |
| Retry | Request the task again according to retry conditions |
| Error | Connect the processing flow based on response information |
This section manages transfer status and final response results as a single processing structure, consolidating content that was previously repeated under status and event handling and error handling.
Integration Verification
Confirm the final transfer result from the application
After completing the integration configuration, run an actual file transfer request from the application and verify the complete processing result.
Confirm that the requested files were processed at the designated destination, and verify the application response together with the file transfer execution record.
Application Request
│
▼
Transfer Run
│
▼
File Processing
│
▼
Result Response
│
┌────┴────┐
▼ ▼
Application Run
Result Record
│ │
└────┬────┘
▼
Final Check

During integration verification, review the overall flow using the following information.
| Review Item | Details |
|---|---|
| Request | Transfer request created by the application |
| Execution | File transfer task created for the request |
| Files | Processed files, file count, and size |
| Target | Designated device or workspace |
| Status | Transfer progress and final result |
| Response | Result information returned to the application |
Developers
Run transfers from business applications and connect progress, control, and results to business data
Integration Preparation
Prepare shared request code and status values
import os
import requests
BASE_URL = os.getenv("INNORIX_BASE_URL", "https://app.innorix.com").rstrip("/")
TOKEN = os.environ["INNORIX_ACCESS_TOKEN"]
WORKSPACE_ID = os.getenv("INNORIX_WORKSPACE_ID") # optional; falls back to the current workspace
STATUS_COMPLETE = 2
TERMINAL = {2, 4, 5, 9, 99} # complete / error / cancelled / partial / failed
NOT_SUCCEEDED = {4, 5, 9, 99}
def api(method, path, body=None, params=None):
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {TOKEN}",
}
if WORKSPACE_ID:
headers["x-workspace-id"] = WORKSPACE_ID
response = requests.request(
method, BASE_URL + path,
headers=headers, json=body, params=params, timeout=30,
)
payload = response.json() if response.content else {}
if not response.ok:
raise RuntimeError(payload.get("message") or f"HTTP {response.status_code}")
return payload.get("data")
def is_terminal(detail):
return detail.get("isTerminal", detail.get("status") in TERMINAL)Determine the transfer status using the values below. There are five terminal states, and the successful state is Complete (2).
| Status Value | Meaning | Terminal |
|---|---|---|
| 2 | Complete | Yes |
| 4 | Error | Yes |
| 5 | Cancelled | Yes |
| 9 | Partially Complete | Yes |
| 99 | Failed | Yes |
| 1 · 6 · 12 · 13 | Started · Transferring · Synchronizing · Receiving | No |
Evaluate terminal status and success separately. Partial completion (9) and cancellation (5) are also terminal states, so treating isTerminal alone as success records failures as successful.
Preflight Validation
Validate paths before starting the transfer
A transfer can be created successfully even when a path is invalid. The failure appears only at execution time, after the business data has already been recorded as in progress.
def validate_paths(source_id, target_id, source_paths, target_path):
# sourceItems reads filePath, not path
return api("POST", "/api/transfers/validate-path", {
"sourceId": source_id,
"targetId": target_id,
"sourceItems": [{"filePath": p} for p in source_paths],
"targetPath": target_path,
}) or {}
result = validate_paths("device-a", "device-b",
["/data/report.pdf"], "/archive")
if result.get("invalidSourcePaths"):
raise ValueError(f"missing source paths: {result['invalidSourcePaths']}")
if result.get("validTargetPath") is False:
raise ValueError("target path not found")| Response Item | Details |
|---|---|
validSourcePaths | Validated source paths |
invalidSourcePaths | Source paths that could not be found |
validTargetPath | Whether the destination path is valid |
Pass each path in sourceItems.filePath. If users enter paths directly in the application, apply this validation when the data is saved.
Create the Transfer
Request transfers by specifying devices, paths, and processing criteria
When sending a file list, explicitly set isDir: false in sourceItem. sourcePaths treats every path as a folder, so supplying files can cause the server to scan each file as a folder, resulting in slowdowns or timeouts.
def create_transfer(source_id, target_id, source_paths, target_path,
action="numbering"):
transfer = api("POST", "/api/transfers/manual", {
"sourceDevice": source_id,
"targetDevice": target_id,
"targetPath": target_path,
"sourceItem": [{"path": p, "isDir": False} for p in source_paths],
"sendAllFolder": False,
"transferOptions": {"target-action": action},
})
return transfer["monitorId"]When sending folders, use sourcePaths with sendAllFolder: True.
api("POST", "/api/transfers/manual", {
"sourceDevice": source_id,
"targetDevice": target_id,
"targetPath": target_path,
"sourcePaths": ["/data/reports"],
"sendAllFolder": True,
"transferOptions": {"target-action": "numbering"},
})Define the handling of same-name files at the destination according to the business purpose.
| Value | Behavior | Suitable Use Case |
|---|---|---|
numbering | Preserve with a sequence number | Workflows that retain submissions by run |
overwrite | Overwrite | Workflows that keep only the latest state |
nosend | Skip without sending when the file already exists | Workflows that must not retransmit the same file |
If settlement data uses overwrite, previous runs are removed, so do not simply use the default; configure the policy for the business requirement.
Files skipped by nosend can cause the transfer to end in a terminal state that is not success. If completion is determined only by status == 2, normal behavior will be counted as a failure, so code using this policy must handle terminal status and success separately.
Connect Business Data
Store monitorId in business data for tracking
The single monitorId returned when a transfer is created is used for subsequent queries, control actions, and retries. Without storing this value in business data, the transfer cannot be traced later.
def start_order_transfer(order_id, source_id, target_id, paths, target_path):
validate_paths(source_id, target_id, paths, target_path)
monitor_id = create_transfer(source_id, target_id, paths, target_path)
db.execute(
"UPDATE orders SET monitor_id = %s, transfer_state = %s WHERE id = %s",
(monitor_id, "transferring", order_id),
)
return monitor_idConversely, there are cases where you need to find business data using monitorId, such as when an operator discovers a problem in the transfer list.
CREATE INDEX idx_orders_monitor_id ON orders (monitor_id);
Display Status
Display progress on screen and determine whether the transfer has ended
import time
def describe(monitor_id):
return api("GET", f"/api/transfers/{monitor_id}")
def wait(monitor_id, timeout=1800, interval=3):
deadline = time.time() + timeout
while time.time() < deadline:
detail = describe(monitor_id)
if is_terminal(detail):
return detail
time.sleep(interval)
raise TimeoutError(monitor_id)
detail = describe(monitor_id)
print(detail["statusLabel"], detail["percent"], "%")
print(detail["transferSize"], "/", detail["totalSize"])| Response Item | Screen Usage |
|---|---|
statusLabel | Status display text |
percent | Progress percentage |
transferSize · totalSize | Transfer volume |
fileCount · folderCount | Transfer scope |
estimateTime | Time remaining |
sourceDeviceName · targetDeviceName | Source and destination |
Polling too frequently creates excessive requests. For screen display purposes, an interval of about 3 seconds is appropriate.
Transfer Control
Pause, resume, or cancel according to user requests
All three actions are called without a request body. However, even when the call succeeds, the status changes only after the instruction reaches the device, so refreshing the screen immediately may still show the previous status.
PAUSED = 3
RUNNING_STATES = {1, 6, 12, 13}
CANCELLED = 5
def control(monitor_id, action, tries=10):
api("POST", f"/api/transfers/{monitor_id}/{action}", {})
expected = {
"pause": {PAUSED},
"resume": RUNNING_STATES,
"cancel": {CANCELLED},
}[action]
for _ in range(tries):
time.sleep(1)
detail = describe(monitor_id)
if detail.get("status") in expected:
return detail
return describe(monitor_id)On the screen, it is natural to disable the button immediately and show that processing is underway, then update the status once the change is confirmed.
When multiple transfers need to be stopped at once, use bulk cancellation.
result = api("POST", "/api/transfers/bulk-cancel", {"monitorIds": monitor_ids})
print(result.get("cancelled"), result.get("failed"))A transfer that has already ended has nothing left to cancel, so cancellation fails and is included in the response's failed field. This is a normal response, not an error.
Confirm the Result
Finalize transfer results in business data and retransmit failed files
def finalize(order_id, monitor_id):
detail = describe(monitor_id)
if not is_terminal(detail):
return None
status = detail["status"]
succeeded = status == STATUS_COMPLETE
db.execute(
"UPDATE orders SET transfer_state = %s, transfer_status = %s WHERE id = %s",
("done" if succeeded else "failed", status, order_id),
)
return succeededStore the status value as well so failure types can be distinguished later. Cancellation (5) and failure (99) require different follow-up actions.
When only some files fail, retransmit only those files.
def failed_files(monitor_id):
result = api("GET", f"/api/transfers/{monitor_id}/files", params={
"state": "any", "size": 500,
}) or {}
return [r for r in (result.get("children") or [])
if r.get("status") in NOT_SUCCEEDED]
def retry_failed(monitor_id):
rows = failed_files(monitor_id)
if not rows:
return 0
api("POST", f"/api/transfers/{monitor_id}/retry", {
"filesRetry": [
{"filePath": r["sourceFilePath"], "isDir": bool(r.get("isFolder"))}
for r in rows
]
})
return len(rows)Each item contains sourceFilePath, statusName, and errorCode, allowing you to show exactly which file failed and why. Retransmission can be called only after the transfer has ended.
If the entire transfer must be run again, retrieve the previous execution information and rerun it.
config = api("GET", f"/api/transfers/{monitor_id}/replay-data")
api("POST", f"/api/transfers/{monitor_id}/replay", {"action": "replay"})| Review Item | Details |
|---|---|
| Request | Validated source and destination |
| Execution | Generated monitorId |
| Status | Progress and terminal status |
| Result | Success status and status value |
| Files | Failed files and error codes |
| Follow-up | Retransmission or rerun result |