Getting Started
Core Concepts
Automatically transfer DB dumps and backup/archive files to designated locations
Databases and backup programs generate various files, including DB dumps, full backup files, incremental backup files, and log archives.
Automated DB and backup file transfer checks for generated files and automatically transfers them to remote data centers or cloud storage according to configured conditions.
By connecting the location where files are generated with the remote storage environment, regularly generated files can be managed through a defined flow.
DB · Backup System
│
▼
Check for File Creation
│
▼
Check Transfer Conditions
│
▼
Remote Storage Environment
│
├── Remote Data Center
│
└── Cloud Storage

Automation Flow
Connect the workflow from backup file creation through remote storage and result confirmation in sequence
When a backup file is created or a backup task is completed, the next transfer task can run according to the configured conditions.
You can also configure a flow that checks files generated on a schedule and transfers them to the remote storage environment.
① Create DB Dump or Backup File
↓
② Confirm File or Backup Completion
↓
③ Run Transfer Task
↓
④ Store in Remote Environment
↓
⑤ Check Results
This flow automatically connects backup file creation and remote storage in the required sequence.
Operational Benefits
Manage regular backup file transfers and remote storage as a single workflow
DB and backup environments continuously manage file creation, remote transfer, storage locations, and execution results.
By configuring an automated transfer flow, regularly generated files can be transferred to designated remote environments while execution results and storage status are reviewed together.
| Category | Individual Management | Automated Transfer |
|---|---|---|
| File Check | Check generated files for each task | Check according to configured conditions |
| Transfer Execution | Run manually for each file | Run automatically according to conditions and schedule |
| Storage Location | Specify the destination for each task | Configure paths by file type |
| Result Management | Review results by task | Review execution records and storage results together |
This lets you configure the entire workflow from DB dump and backup file creation through remote storage as a single operational flow.
IT Engineers
Source Connection
Connect file creation locations on database and backup systems
First, connect the systems and folders where DB dumps and backup files are created to the transfer environment.
Specify file paths generated on database servers, backup servers, or storage systems and configure them as transfer sources.
| Source Environment | Generated Files |
|---|---|
| Database Server | DB dumps and export files |
| Backup Server | Full and incremental backup files |
| Log Server | Transaction logs and archives |
| Storage | Files intended for long-term retention |
![]() |
Transfer Configuration
Configure the remote storage location and execution conditions as a single transfer flow
After connecting the source files, configure a remote data center or cloud storage as the transfer destination.
You can configure transfer tasks to start when a file is created, when a backup task is completed, or according to a defined schedule.
| Configuration Item | Configuration |
|---|---|
| Remote Destination | Data center or cloud storage |
| Storage Location | Folder or bucket path by file type |
| Execution Conditions | File creation, backup completion, scheduled execution |
| File Type | DB Dump, Backup, Archive, etc. |
For example, you can transfer daily backups to cloud storage while sending weekly backups and long-term retention files to separate remote paths.
Backup Task
│
▼
Backup Complete
│
▼
Check Files
│
├── DB Dump ────────────→ Remote Data Center
│
├── Daily Backup ───────→ Cloud Storage
│
└── Archive ────────────→ Long-Term Retention Path

Automated Transfer
Automatically transfer generated backup files to designated remote environments
When the configured conditions are met, transfer DB dumps and backup files to the designated remote environment.
You can branch files to different storage locations based on file type and path, or transfer a single backup file to multiple remote environments at the same time.
Backup File
│
▼
Transfer Task
╱ ╲
▼ ▼
Remote Data Center Cloud Storage
│ │
▼ ▼
Backup Storage Bucket / Path

Result Management
Check transfer status and storage results, then rerun tasks when necessary
When a transfer task runs, use Runs and task details to review file processing status and remote storage results.
When a specific task requires additional review, use the Activity Log and execution information to check the source file, system connection, destination path, and access scope before rerunning the required task.
Run Transfer
│
▼
Check Task Status
│
├── Running
│ │
│ └── Check Progress
│
├── Completed
│ │
│ └── Check Storage Result
│
└── Review Required
│
▼
Review Detailed Records
│
▼
Check Source · Connection · Storage Path
│
▼
Rerun Required Task
│
▼
Check Result Again
| Review Item | Details |
|---|---|
| Source File | Transferred DB dumps and backup files |
| Destination | Remote server or cloud storage path |
| Progress Status | Current task status and progress |
| Processing Result | Number of transferred files and total size |
| Execution Record | File processing stages and task results |

Developers
Transfer the dump to a remote location when the backup completes and verify it with a checksum
Integration Preparation
Prepare shared request code and path conventions
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)import base64
import time
def encode_path(device_id, raw_path):
normalized = str(raw_path or "").replace("\\", "/")
token = base64.b64encode(normalized.encode("utf-8")).decode("ascii")
return f"{device_id}_ino_{token}"
def now_iso():
return time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime())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 |
Transfer After Backup Completion
Continue the transfer at the end of the backup script
Calling the transfer immediately after the backup program creates the file lets you align the transfer precisely with the point when the file is ready.
When sending files, explicitly set isDir: false in sourceItem. sourcePaths treats every path as a folder, so providing a dump file can cause the server to scan it as a folder, resulting in slowdowns or timeouts.
import glob
import os
def latest_backup(directory, pattern="*.dump"):
files = glob.glob(os.path.join(directory, pattern))
if not files:
raise FileNotFoundError(directory)
return max(files, key=os.path.getmtime)
def send_backup(source, target, backup_path, target_path):
transfer = api("POST", "/api/transfers/manual", {
"sourceDevice": source,
"targetDevice": target,
"targetPath": target_path,
"sourceItem": [{
"path": backup_path,
"isDir": False,
"fileSize": os.path.getsize(backup_path),
}],
"sendAllFolder": False,
"checkIntegrity": True,
"transferOptions": {"target-action": "numbering"},
})
return transfer["monitorId"]Backup files must retain their run history, so set the destination policy to numbering. With overwrite, previous backups disappear and you cannot choose the recovery point.
Providing the file size as well makes the operation faster because the server does not need to retrieve the size of each item again.
Because a corrupted backup may not be discovered until recovery is attempted, use checkIntegrity to verify integrity during the transfer stage.
Branch by File Type
Send dumps, incrementals, and archives to different locations
A single transfer handles one destination. When destinations differ by file type, create separate transfers.
ROUTES = {
"dump": ("device-dc-01", "/backup/dump"),
"daily": ("device-cloud-01", "/backup/daily"),
"archive": ("device-archive-01", "/backup/archive"),
}
def classify(filename):
name = os.path.basename(filename).lower()
if name.endswith(".dump"):
return "dump"
if "archive" in name or name.endswith(".tar.gz"):
return "archive"
return "daily"
def dispatch(source, files):
transfers = {}
for path in files:
target, target_path = ROUTES[classify(path)]
transfers[path] = send_backup(source, target, path, target_path)
return transfersWhen a single backup file must be sent to multiple remote environments, create a transfer for each destination and store the returned monitorId for each destination so the individual transfers can be queried later.
copies = {
target: send_backup("device-db-01", target, backup_path, path)
for target, path in [("device-dc-01", "/backup/dump"),
("device-cloud-01", "/backup/mirror")]
}Schedule Automation
Register the task to run repeatedly at a defined time
If the backup script cannot be modified, use schedule automation instead.
def build_schedule_automation(name, source, source_path, target, target_path,
schedule):
return {
"name": name,
"flowName": name,
"transferType": "normal",
"timezone": "Asia/Seoul",
"step": 1,
"isUpcoming": False,
"details": [
{
"senderId": source,
"receiverId": target,
"sourceItem": [
{
"hash": encode_path(source, source_path),
"filePath": source_path,
"isDir": True,
}
],
"targetPath": encode_path(target, target_path),
"step": 1,
"transferOptions": {
"noSchedule": False,
"target-action": "numbering",
"send-fileoption": {},
},
}
],
"schedules": [schedule],
}
DAILY_3AM = {
"type": "day",
"startDateType": "now",
"hour": "03",
"minute": "00",
"ampm": "am",
"startDate": now_iso(),
"timezone": "Asia/Seoul",
}
MONTHLY = {
"type": "month",
"startDateType": "now",
"day": "1",
"hour": "04",
"minute": "00",
"ampm": "am",
"startDate": now_iso(),
"timezone": "Asia/Seoul",
}
api("POST", "/api/automations", build_schedule_automation(
"daily backup", "device-db-01", "/backup",
"device-dc-01", "/backup/daily", DAILY_3AM))There are four requirements that must always be followed when creating an automation request.
| Item | How to Configure |
|---|---|
isUpcoming | Must be false. The server default of true ignores the schedule in the request and replaces it with a one-time five-minute schedule. A stage with triggerAutomation forces the value to false, so you only need to set it directly on the first stage without a trigger |
step | Set it in both the top level and details. It indicates the hop position within the workflow |
sourceItem | Include both hash (the path token) and filePath (the plain-text path) |
syncType | Set it inside transferOptions. 1 is one-way and 2 is two-way |
Registration succeeds even if all four items are omitted, but the behavior changes at execution time. If a recurring schedule was registered but runs only once, check isUpcoming first.
Prevent Duplicate Registrations
Prevent the same backup task from being created twice
Even if an automation with the same name already exists, a new one is created. If a batch is retried, the same backup is transferred twice, and because the destination policy is numbering, two copies of the file accumulate.
def find_automation(name):
# the name we send is stored as flowName in the response
# automationName is a server generated id like T4037-8500-1815, not the name we set.
for page in range(1, 6):
result = api("GET", "/api/automations",
params={"page": page, "size": 100, "search": name}) or {}
items = [item
for flow in result.get("automations") or []
for item in flow.get("automations") or []]
for item in items:
if item.get("flowName") == name:
return item
if len(items) < 100:
return None
return NoneThe automation list is returned nested by flow group, so you must iterate through the inner arrays as well. Server search uses partial matching, so select only the item whose name exactly matches from the returned results.
Integrity Verification
Verify that the backup stored remotely matches the source
def verify(monitor_id, timeout=1800, interval=10):
api("POST", f"/api/transfers/{monitor_id}/verification", {})
deadline = time.time() + timeout
while time.time() < deadline:
result = api("GET", f"/api/transfers/{monitor_id}/verification") or {}
if result.get("verified"):
return result
time.sleep(interval)
raise TimeoutError(monitor_id)result = verify(monitor_id)
if not result["checksumMatched"]:
alert(f"backup integrity failed: {result.get('mismatchedFiles')}")| Response Item | Details |
|---|---|
checksumAlgorithm | Checksum algorithm used |
sourceFileCount · targetFileCount | Source and remote file counts |
checksumMatched | Whether the checksums match |
mismatchedCount | Number of mismatches |
If the file counts differ, the transfer is incomplete. If the counts match but there are mismatches, the contents are corrupted. The latter is more dangerous for backups, so report verification failures immediately.
Verify Results and Retransmit
Check transfer results and retransmit failed files
def wait(monitor_id, timeout=3600, interval=3):
deadline = time.time() + timeout
while time.time() < deadline:
detail = api("GET", f"/api/transfers/{monitor_id}")
if is_terminal(detail):
return detail
time.sleep(interval)
raise TimeoutError(monitor_id)
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)detail = wait(monitor_id, timeout=7200)
if detail["status"] != STATUS_COMPLETE:
alert(f"backup transfer failed - retried {retry_failed(monitor_id)} files")To check whether the previous run of a daily task ended successfully, query recent history over a defined period.
from datetime import datetime, timedelta, timezone
def paginate(path, params=None, limit=200, max_pages=50):
query = dict(params or {})
query["limit"] = limit
cursor = None
for _ in range(max_pages):
if cursor:
query["cursor"] = cursor
result = api("GET", path, params=query) or {}
for record in result.get("data") or []:
yield record
pagination = result.get("pagination") or {}
if not pagination.get("hasMore"):
return
cursor = pagination.get("nextCursor")
if not cursor:
return
end = datetime.now(timezone.utc)
fmt = "%Y-%m-%dT%H:%M:%SZ"
rows = list(paginate("/api/transfer-history", params={
"startDate": (end - timedelta(days=1)).strftime(fmt),
"endDate": end.strftime(fmt),
}))
failures = [r for r in rows if r.get("status") in NOT_SUCCEEDED]
if failures:
alert(f"{len(failures)} backup transfers failed yesterday")When the complete history is needed as an audit file, use CSV export.
params = {
"periodDays": 30,
"page": 1,
"size": 10000,
"filter": "[]", # the server parses this as a JSON string, so send an empty array
"sort": "startDate:desc",
}Even when there are no conditions, send an empty array string ("[]") in filter because the server parses this value as JSON. The fields allowed in sort are status, sourceDeviceName, targetDeviceName, totalSize, sourceFileCount, startDate, endDate, automationName, formattedTransferTime, and savedTime.
| Review Item | Details |
|---|---|
| Source | Transferred dumps and backup files |
| Destination | Remote data center or cloud path |
| Verification | Whether file counts and checksums match |
| Status | Transfer status and success |
| History | Execution result for the most recent run |
| Retransmission | Failed files and processing result |
