Getting Started
Basic Concept
Manage File Transfers Separately by Workspace
A file workspace is a way to organize the files, storage locations, transfer targets, and access scope used for a specific task into a single space.
For example, files used by development, content, and data analysis teams can be organized into separate workspaces, with the required storage locations and transfer devices connected to each workspace.
File Workspace
│
┌────┼───────────────┐
▼ ▼ ▼
Files Storage Access
│ │ │
▼ ▼ ▼
Transfer Targets Users / Devices

This configuration lets you separate and manage files and transfer environments by workspace across multiple business tasks.
Workspace Flow
Continue from File Storage to Transfer and Result Verification
Users select a workspace with configured access permissions and store or check the required files.
When a transfer job connected to the workspace is run, the selected files are transferred to the specified devices and business environments, and the execution result can also be checked in the same workspace.
Select Workspace
│
▼
Store · Check Files
│
▼
Run Transfer Job
│
▼
Reflect on Target Device
│
▼
Check Processing Result

Separation Benefits
Manage Files from Multiple Tasks and Devices by Purpose
Organizing workspaces by task lets you manage files, storage locations, transfer targets, and access scope under a single management standard.
| Category | Individual Management | Workspace Management |
|---|---|---|
| Files | Check files in multiple locations individually | Manage task-specific files by workspace |
| Storage Location | Check the location for each file | Configure storage locations by workspace |
| Transfer Target | Check the target for each job | Connect transfer devices and paths by workspace |
| Access Scope | Check files by user | Manage access scope by workspace |
| Result Verification | Check results by job | Check execution results by workspace |
Business Team
Manage and Use Required Files in Workspaces
Workspace Selection
Check Task-Specific Files and Work in One Place
When starting a task, select the workspace containing the required files and jobs.
A workspace contains the files used for the task together with connected transfer jobs, allowing the responsible user to perform file operations in the workspace required for the current task.
My Workspaces
│
├── Project A
│ ├── Files
│ └── Transfers
│
├── Media Team
│ ├── Files
│ └── Transfers
│
└── Data Analysis
├── Files
└── Transfers

File Usage
Store Required Files and Use Them in the Next Task
Store the files required for the task in the workspace and check the files to use for the current work.
Stored files can be used with the business flow connected to the workspace, allowing the responsible user to select the required files and continue to the next task.
Workspace
│
├── Upload Files
│
├── Browse Files
│
└── Select Files
│
▼
Next Work
Run Transfer
Send Files Using a Prepared Transfer Job
After selecting the required files, run the transfer job configured in the workspace.
The responsible user can select the files to use for the current task and the job to run, then check progress and processing results.
Select Files
│
▼
Select Transfer
│
▼
Run
│
┌────┴────┐
▼ ▼
Progress Target
│ │
└────┬────┘
▼
Result

Business teams can manage required files in workspaces and use prepared transfer flows to continue to the next task.
IT Engineer
Configure File Workspaces and Transfer Environments and Manage Them Centrally
Workspace Setup
Configure File Storage Locations and Management Scope by Task
Create workspaces according to business purposes and configure the file storage locations and management scope used by each workspace.
For example, development outputs, media files, and data processing results can each be organized into separate workspaces.
Organization
│
┌────┼───────────────┐
▼ ▼ ▼
Dev Media Data
│ │ │
▼ ▼ ▼
Storage Storage Storage
Transfer Connection
Connect Workspaces, Target Devices, and File Paths
Connect the transfer target devices and file paths used by each workspace.
Connect servers, storage, and business devices to workspaces and configure file transfer paths to build task-specific transfer environments.
Workspace
│
├── Source Storage
│
├── Transfer Flow
│
└── Target Devices
│
┌──────┼──────┐
▼ ▼ ▼
Server Storage System

Access Policy
Manage Access Scope and Transfer Rules by User and Device
For each workspace, configure user and group access scope, connectable devices, file paths, and transfer jobs that can be run.
When the business environment or user configuration changes, adjust access scope and processing rules from the same policy screen.
Workspace Policy
│
┌─────┼────────────┐
▼ ▼ ▼
Users Groups Devices
│ │ │
▼ ▼ ▼
Access Operations Paths
│
▼
Transfer Rules

| Management Item | Configuration |
|---|---|
| Workspace | Workspaces by user and task |
| Users / Groups | Users and groups that use the workspace |
| Devices | Connectable devices |
| Paths | Paths used for files |
| Operations | File operations that can be run |
| Transfer Rules | File transfer criteria and processing rules |
Operations Management
Check Transfer Results by Workspace and Overall Operational Status
Check file transfers and processing results for each workspace and centrally manage the status of multiple workspaces and connected devices.
Operators can check the execution status of a specific workspace or understand the operational situation based on job status across the entire environment.
Central Management
│
┌──────┼───────────────┐
▼ ▼ ▼
Workspace Devices Runs
│ │ │
└────────┼──────────────┘
▼
Operations View

Workspaces can be configured and managed through the following flow.
Configure Workspace
│
▼
Connect Storage Location
│
▼
Set Target Devices · Transfer Paths
│
▼
Configure User · Device Access Policies
│
▼
Run Transfer Job
│
▼
Check Workspace-Specific · Overall Operational Status
Developer
Include the Workspace Identifier and Token in Requests and Handle Permission Responses
Authentication Handling
Issue Tokens and Refresh Them When They Expire
The workspace API uses an access token for authentication. If no token is available, log in with the account to obtain one.
import os
import threading
import requests
BASE_URL = os.getenv("INNORIX_BASE_URL", "https://app.innorix.com").rstrip("/")
def login(email, password):
response = requests.post(f"{BASE_URL}/api/auth/login",
json={"email": email, "password": password},
timeout=30)
response.raise_for_status()
# the login response nests the tokens under data.user
user = response.json()["data"]["user"]
return user["accessToken"], user.get("refreshToken")
def refresh(refresh_token):
response = requests.post(f"{BASE_URL}/api/auth/token/refresh",
headers={"X-Refresh-Token": refresh_token},
timeout=30)
response.raise_for_status()
# the refresh response nests the tokens directly under data
data = response.json()["data"]
return data["accessToken"], data.get("refreshToken")The response structures for login and refresh are different. Login nests the tokens under data.user, while refresh places them directly under data.
A refresh token is valid only once. If a server application uses the same token across multiple threads, lock the refresh operation so it cannot occur concurrently.
class Session:
def __init__(self, email, password):
self._lock = threading.Lock()
self._access, self._refresh = login(email, password)
@property
def access_token(self):
with self._lock:
return self._access
def renew(self):
with self._lock:
self._access, self._refresh = refresh(self._refresh)
return self._accessWorkspace Assignment
Send the Workspace Identifier with Every Request
The workspace is passed in a header rather than the request body. Because specifying it at each call site can lead to omissions, centralize request construction in one place.
class Client:
def __init__(self, session, workspace_id=None):
self.session = session
self.workspace_id = workspace_id
def request(self, method, path, body=None, params=None, retried=False):
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {self.session.access_token}",
}
# when omitted the account's current workspace is used
if self.workspace_id:
headers["x-workspace-id"] = self.workspace_id
response = requests.request(method, BASE_URL + path, headers=headers,
json=body, params=params, timeout=30)
if response.status_code == 401 and not retried:
self.session.renew()
return self.request(method, path, body, params, retried=True)
return responseIf no workspace identifier is specified, the account's currently accessible workspace is used. An application that uses a single workspace can operate without specifying one.
Token expiration is also handled at this point. When a 401 is received, refresh once and retry; if the retried request fails again, propagate the failure as-is.
Check Access Scope
Check the Account's View Scope and Accessible Devices
me = api("GET", "/api/auth/me") or {}
print(me)
result = api("GET", "/api/devices", params={"page": 1, "size": 20}) or {}
if result.get("viewScope"):
print("view scope:", result["viewScope"])
for device in result.get("devices") or []:
print(device["deviceId"], device["name"])| Response Item | Details |
|---|---|
devices | List of devices connected to the workspace |
totalRows · lastPage | Total count and last page |
viewScope | Current account view scope |
The device list is returned as the data.devices array. Use viewScope in the response to determine whether the account can view everything or only part of the environment.
Permission Handling
Distinguish 401 and 403 and Handle Them with Re-login or UI Guidance
Authentication failure and insufficient permissions must be handled differently. The former requires re-login, while the latter requires UI guidance.
| Status | Meaning | Handling |
|---|---|---|
| 401 | Token is missing or invalid | Refresh and retry; if it fails, re-login |
| 403 | Cannot access the workspace or path | Inform the user |
| 404 | Device or path does not exist | Inform the user that the target is no longer available |
| 429 | Too many requests | Retry after a short delay |
class WorkspaceForbidden(Exception):
pass
def call(client, method, path, body=None, params=None):
response = client.request(method, path, body, params)
if response.status_code == 403:
raise WorkspaceForbidden(path)
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")
try:
devices = call(client, "GET", "/api/devices")
except WorkspaceForbidden:
devices, notice = [], "no permission to access this workspace"Separating insufficient permissions into a dedicated exception lets the calling code convert them into a user-facing message. Because results can differ by workspace even for the same user, display the current workspace at the top of the UI so users do not mistake an empty list for a permission problem.
Multi-Workspace Handling
Separate Credentials in Code That Handles Multiple Workspaces
Passing the workspace identifier as a function argument can lead to omissions at some call site. Create a client for each workspace and pass the client object instead.
clients = {
workspace_id: Client(session, workspace_id)
for workspace_id in WORKSPACE_IDS
}
def collect_devices():
result = {}
for workspace_id, client in clients.items():
try:
result[workspace_id] = call(client, "GET", "/api/devices")
except WorkspaceForbidden:
continue
return resultThere is no endpoint for listing workspaces. Provide candidate workspaces and filter them to determine which are accessible.
If each customer has a separate account, separate the sessions as well. Keep their creation points separate so they are not mixed with a configuration where multiple workspaces share one session.
def build_client(config):
session = Session(config["email"], config["password"])
return Client(session, config["workspace_id"])
clients = {name: build_client(cfg) for name, cfg in TENANTS.items()}A batch that iterates over multiple workspaces should not let a failure in one workspace stop the entire batch.
failed = []
for name, client in clients.items():
try:
run_for(client)
except Exception as error:
failed.append((name, error))
for name, error in failed:
print(f"{name}: {error}")| Management Item | Handled in Code |
|---|---|
| Session | Access and refresh tokens by account |
| Workspace | Workspace identifier in the request header |
| Permissions | 403 response and UI guidance |
| Resources | Devices and view scope by workspace |
| Execution | Transfers created within the workspace |