MFX Hub
SDK reference

Terminals

Generated from mfx-sdk-python 0.9.11·rebuilt on every release

Provision, inspect, drain and retire the terminals your key's tenant owns.

Types

AliasValues
RedundancyLiteral['none', 'active_passive', 'active_active']
CredentialTypeLiteral['master', 'investor']
TimeframeLiteral['M1', 'M5', 'M15', 'M30', 'H1', 'H4', 'D1', 'W1', 'MN1']
Idstr | UUID

Terminals

Provision, inspect, drain and retire the terminals this key's tenant owns.

async create( *, broker_id: Id, server_id: Id, idempotency_key: str, farm_id: Id | None = None, streaming: bool = False, execution: bool = False, instruments: list[str] | None = None, labels: dict[str, str] | None = None, redundancy: Redundancy = 'none', ) -> TenantTerminal

Ask for a terminal. Answered at once in state REQUESTED.

ParameterTypeDefaultDescription
broker_id keywordIdrequired

The broker's id from the catalogue.

server_id keywordIdrequired

The server's id from the catalogue.

idempotency_key keywordstrrequired

Required on every write and never defaulted. Retrying with the same key returns the original answer; a fresh key asks for a new action.

farm_id keywordId | NoneNone

Where to place the terminal. Leave it out and the platform chooses; name one to place it deliberately.

streaming keywordboolFalse

Whether this terminal streams market data.

execution keywordboolFalse

Whether this terminal may trade.

instruments keywordlist[str] | NoneNone

The broker's own symbol names to subscribe on creation.

labels keyworddict[str, str] | NoneNone

Your own key/value labels on the terminal, for your own filtering.

redundancy keywordRedundancy'none'

"none", "active_passive" or "active_active": whether the terminal keeps a warm stand-in.

Returns TenantTerminal

The move to capacity is asynchronous, and the credential is submitted separately, so a terminal exists before its login does. instruments are the broker's own symbol names (EURUSD.sd): MFX never renames an instrument on a tenant's behalf.

farm_id is optional. Leave it out and the platform chooses: your own ACTIVE farms first, then the shared ones, offering the usages this terminal needs, in the server's region, with room; the oldest wins a tie. The farm it picked is on the answer, so the choice is never silent. Nothing fits is 409 no_farm rather than a terminal parked somewhere it cannot run. client.farms.list shows what could be chosen from.

Naming one is still the way to place a terminal deliberately, and it is checked rather than trusted: a farm that is not yours, or cannot take it, is refused.

async get(terminal_id: Id) -> TenantTerminal

One terminal: its state, how long it has been in it, and its observed conditions.

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

Returns TenantTerminal

Another tenant's id is a 404, never a 403.

async page(*, cursor: str | None = None, limit: int | None = None) -> Page[TenantTerminal]

One page of this tenant's terminals, newest first.

ParameterTypeDefaultDescription
cursor keywordstr | NoneNone

Where to continue from; the previous page's next cursor.

limit keywordint | NoneNone

How many to return at most.

Returns Page[TenantTerminal]

async list(*, limit: int | None = None) -> AsyncIterator[TenantTerminal]

Every terminal, following the cursor.

ParameterTypeDefaultDescription
limit keywordint | NoneNone

How many to return at most.

Returns AsyncIterator[TenantTerminal]

There is no total and no page number anywhere in the API, and there never will be (guardrail 7), so this follows the cursor rather than counting.

async submit_credentials( terminal_id: Id, *, login: int, password: Secret | str, server: str, idempotency_key: str, cred_type: CredentialType = 'master', ) -> CredentialAccepted

Put a broker login on a terminal. The only request in MFX that carries a secret.

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

login keywordintrequired

The broker login.

password keywordSecret | strrequired

The broker password, wrapped in Secret. It travels once and is used by reference.

server keywordstrrequired

The broker server name as the broker publishes it.

idempotency_key keywordstrrequired

Required on every write and never defaulted. Retrying with the same key returns the original answer; a fresh key asks for a new action.

cred_type keywordCredentialType'master'

Returns CredentialAccepted

It is wrapped, written to Key Vault and never stored, logged or echoed; the answer is a reference and nothing else. An investor credential turns execution off, and execution_disabled on the answer says so here rather than at the first refused order.

async restart( terminal_id: Id, *, reason: str, idempotency_key: str, confirm_open_positions: bool = False, ) -> OperationAccepted

Restart a stuck terminal: the terminal is closed and started again on the same host.

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

reason keywordstrrequired

Your own words, recorded with the action.

idempotency_key keywordstrrequired

Required on every write and never defaulted. Retrying with the same key returns the original answer; a fresh key asks for a new action.

confirm_open_positions keywordboolFalse

confirm_open_positions has no default on purpose at the platform: a restart drops the broker session for a few seconds, and on an account with positions open that is a decision the caller makes deliberately.

Returns OperationAccepted

Answered 202 with the operation to follow; the terminal is not back until the operation succeeds, which takes a minute or two. reason is required and is shown to operators in the console's activity feed and read back by this API, so it is written for a person, not for a tracker.

confirm_open_positions has no default on purpose at the platform: a restart drops the broker session for a few seconds, and on an account with positions open that is a decision the caller makes deliberately. Positions live at the broker and are not closed by a restart; the flag is there so nobody does this to a live account without saying so.

Seven rules govern it: a cooldown, a rate limit, one operation at a time per terminal, and the states a restart can act on. A refusal names its rule in error.code, with Retry-After when waiting is what helps.

async replace_instruments( terminal_id: Id, instruments: Sequence[str], *, depth_instruments: Sequence[str] | None = None, idempotency_key: str, ) -> TenantTerminal

Replace the terminal's whole instrument list, in the broker's own names.

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

instrumentsSequence[str]required

The broker's own symbol names to subscribe on creation.

depth_instruments keywordSequence[str] | NoneNone

depth_instruments are the symbols of instruments whose order book it reads and streams on book: the whole list; [] stops depth; left out, the terminal keeps the depth symbols still in instruments.

idempotency_key keywordstrrequired

Required on every write and never defaulted. Retrying with the same key returns the original answer; a fresh key asks for a new action.

Returns TenantTerminal

depth_instruments are the symbols of instruments whose order book it reads and streams on book: the whole list; [] stops depth; left out, the terminal keeps the depth symbols still in instruments. A farm that offers no depth answers 422 depth_not_offered; more than the farm allows, or a symbol not in instruments, is 422 unprocessable. Many brokers publish no book for most FX symbols; asking costs nothing then and the channel stays quiet.

async attach_expert_advisor( terminal_id: Id, expert_advisor_id: Id, *, symbol: str, timeframe: Timeframe, reason: str, idempotency_key: str, queue: bool = False, confirm_open_positions: bool = False, ) -> OperationAccepted

Attach an approved version to this terminal, on the symbol's chart and timeframe. A governed relaunch, answered 202 with the operation to follow (wait_for_operation). The expert then runs its trial with trading off; it trades only after a green trial, and on a real-money account only after confirm_expert_advisor.

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

expert_advisor_idIdrequired
symbol keywordstrrequired

The broker's own symbol name, exactly as the catalogue returns it. MFX Hub never renames an instrument.

timeframe keywordTimeframerequired

One of M1, M5, M15, M30, H1, H4, D1, W1, MN1.

reason keywordstrrequired

Your own words, recorded with the action.

idempotency_key keywordstrrequired

Required on every write and never defaulted. Retrying with the same key returns the original answer; a fresh key asks for a new action.

queue keywordboolFalse
confirm_open_positions keywordboolFalse

Returns OperationAccepted

async detach_expert_advisor( terminal_id: Id, *, reason: str, idempotency_key: str, queue: bool = False, confirm_open_positions: bool = False, ) -> OperationAccepted

Take the expert off this terminal: a governed relaunch that rebuilds the folder, 202.

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

reason keywordstrrequired

Your own words, recorded with the action.

idempotency_key keywordstrrequired

Required on every write and never defaulted. Retrying with the same key returns the original answer; a fresh key asks for a new action.

queue keywordboolFalse
confirm_open_positions keywordboolFalse

Returns OperationAccepted

async confirm_expert_advisor(terminal_id: Id, *, code: str) -> ExpertAdvisorAttachment

Turn on live trading on a real-money account after a green trial, with the one-time code sent to the account's representative. A wrong, used or expired code is 403 confirmation_refused and the answer does not say which; five in a row lock it.

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

code keywordstrrequired

Returns ExpertAdvisorAttachment

async get_operation(terminal_id: Id, operation_id: Id) -> TerminalOperation

One operation on the terminal (restart, attach, detach): its state, step and timeline.

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

operation_idIdrequired

Returns TerminalOperation

async wait_for_operation( terminal_id: Id, operation_id: Id, *, timeout_s: float = 900.0, ) -> TerminalOperation

Read the operation until it is over (OPERATION_FINAL), or until timeout_s. Returns the last read either way: an operation still running when the time runs out is reported as it is. Serves restart, attach and detach alike.

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

operation_idIdrequired
timeout_s keywordfloat900.0

Read the operation until it is over (OPERATION_FINAL), or until timeout_s.

Returns TerminalOperation

async drain( terminal_id: Id, *, idempotency_key: str, reason: str | None = None, confirm_open_positions: bool = False, ) -> TenantTerminal

Close the terminal gracefully and keep it: DRAINED holds no host and is not billed.

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

idempotency_key keywordstrrequired

Required on every write and never defaulted. Retrying with the same key returns the original answer; a fresh key asks for a new action.

reason keywordstr | NoneNone

Your own words, recorded with the action.

confirm_open_positions keywordboolFalse

confirm_open_positions is required true when the account has positions open (409 positions_open); positions stay open at the broker while the terminal is drained.

Returns TenantTerminal

Answered with the terminal DRAINING; it is DRAINED once its host has stopped it, and the operation (kind drain) succeeds. A drained terminal keeps its id, account, credential, instruments, labels and expert-advisor record and runs nothing until resume. It still counts toward the terminal quota. Retire it with retire.

Governed as restart is: one operation at a time, a cooldown, the tenant's rate and the farm's blast radius, each refusal naming its rule. confirm_open_positions is required true when the account has positions open (409 positions_open); positions stay open at the broker while the terminal is drained. reason goes to the audit log and the terminal's history; left out, it is recorded as not given.

async resume(terminal_id: Id, *, idempotency_key: str) -> TenantTerminal

Place a DRAINED terminal again: back to REQUESTED, then placed and logged in as new.

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

idempotency_key keywordstrrequired

Required on every write and never defaulted. Retrying with the same key returns the original answer; a fresh key asks for a new action.

Returns TenantTerminal

What can never work is refused at once - its farm not taking terminals, its broker or server no longer supported, a usage its farm no longer offers. Otherwise it waits for room as a new terminal does and is billed again from ACTIVE. A terminal already on its way back is answered as it is, so a resume sent twice is one resume; a DRAINING one is 409 state_error until it is DRAINED.

async retire(terminal_id: Id, *, idempotency_key: str) -> TenantTerminal

Retire a terminal: it drains, then retires. Answered with its state now (DRAINING).

ParameterTypeDefaultDescription
terminal_idIdrequired

The terminal to act on. Another customer's id answers 404, never 403.

idempotency_key keywordstrrequired

Required on every write and never defaulted. Retrying with the same key returns the original answer; a fresh key asks for a new action.

Returns TenantTerminal