Your trading terminals, in the cloud, driven by your code.
MFX Hub runs your MetaTrader 5® terminals and connects your cTrader accounts, keeps them healthy around the clock, and gives your application one signed API and typed SDKs for trading, account data, market data and live events. Any broker. You stay the account holder and the licensee; we provide the infrastructure, the management and the support.
Trade
Market and pending orders, modify, close, partial close, and a server-side trailing stop. Every write is idempotent, and every rejection carries the broker's own return code and text.
Trading featuresAccount data
Balance, equity, margin, open positions, pending orders and deal history, read from the live terminal and streamed as they change.
Account featuresMarket data
Ticks, candles and market depth from your broker's own feed, under your broker's own symbol names, which MFX Hub never renames.
Market data featuresYour expert advisors
Upload your own advisor. We build it, audit the code on your behalf, trial it on one terminal and run it beside your terminal with its notes streamed back to you.
How the audit worksA terminal in a dozen lines, in your language
Request a terminal, send the credential once, wait for ACTIVE, trade. The private key is shown once at issue and never stored by MFX Hub; secrets render as *** in every log line.
- Typed end to end, generated from the same contract the API is built from.
- Execution methods never raise: a timeout or a broker rejection is a result you can read.
- Broker latency and platform latency reported separately on every call.
import os, anyio, mfx
async def main():
async with mfx.MfxClient("https://api.mfxhub.com/v1", os.environ["MFX_KEY_ID"], os.environ["MFX_PRIVATE_KEY"]) as client:
terminal = await client.terminals.create(
broker_id=BROKER, server_id=SERVER,
streaming=True, instruments=["EURUSD"],
idempotency_key="first-terminal-2026-10-20",
)
await client.terminals.submit_credentials(
terminal.id, login=1234567, password=mfx.Secret(os.environ["BROKER_PASSWORD"]),
server="YourBroker-Live", idempotency_key="first-credential-2026-10-20",
)
while (t := await client.terminals.get(terminal.id)).state.value not in ("ACTIVE", "FAILED"):
print(t.state.value, [c.code for c in t.conditions])
await anyio.sleep(5)
result = await client.execution.place_order(
terminal.id, symbol="EURUSD", side="buy", volume="0.10",
idempotency_key="order-0001",
)
# result.ok, result.reason, result.broker_latency_ms, result.agent_latency_ms
anyio.run(main)import { MfxClient, Secret } from "@mfxhub/sdk";
const client = new MfxClient("https://api.mfxhub.com/v1", process.env.MFX_KEY_ID!, process.env.MFX_PRIVATE_KEY!);
const terminal = await client.terminals.create({
brokerId: BROKER, serverId: SERVER,
streaming: true, instruments: ["EURUSD"],
idempotencyKey: "first-terminal-2026-10-20",
});
await client.terminals.submitCredentials(terminal.id, {
login: 1234567, password: new Secret(process.env.BROKER_PASSWORD!),
server: "YourBroker-Live", idempotencyKey: "first-credential-2026-10-20",
});
await client.terminals.waitFor(terminal.id, "ACTIVE", { timeoutMs: 120_000 });
const result = await client.execution.placeOrder(terminal.id, {
symbol: "EURUSD", side: "buy", volume: "0.10", idempotencyKey: "order-0001",
});
// result.ok, result.reason, result.brokerLatencyMs, result.agentLatencyMsusing MfxHub;
await using var client = new MfxClient("https://api.mfxhub.com/v1", keyId, privateKey);
var terminal = await client.Terminals.CreateAsync(new CreateTerminal {
BrokerId = BROKER, ServerId = SERVER,
Streaming = true, Instruments = ["EURUSD"],
IdempotencyKey = "first-terminal-2026-10-20",
});
await client.Terminals.SubmitCredentialsAsync(terminal.Id, new Credential {
Login = 1234567, Password = Secret.From(Environment.GetEnvironmentVariable("BROKER_PASSWORD")),
Server = "YourBroker-Live", IdempotencyKey = "first-credential-2026-10-20",
});
await client.Terminals.WaitForAsync(terminal.Id, TerminalState.Active, TimeSpan.FromMinutes(2));
var result = await client.Execution.PlaceOrderAsync(terminal.Id, new PlaceOrder {
Symbol = "EURUSD", Side = Side.Buy, Volume = 0.10m, IdempotencyKey = "order-0001",
});
// result.Ok, result.Reason, result.BrokerLatencyMs, result.AgentLatencyMsimport com.mfxhub.sdk.*;
try (MfxClient client = MfxClient.create("https://api.mfxhub.com/v1", keyId, privateKey)) {
Terminal terminal = client.terminals().create(CreateTerminal.builder()
.brokerId(BROKER).serverId(SERVER)
.streaming(true).instruments(List.of("EURUSD"))
.idempotencyKey("first-terminal-2026-10-20").build());
client.terminals().submitCredentials(terminal.id(), Credential.builder()
.login(1234567).password(Secret.of(System.getenv("BROKER_PASSWORD")))
.server("YourBroker-Live").idempotencyKey("first-credential-2026-10-20").build());
client.terminals().waitFor(terminal.id(), TerminalState.ACTIVE, Duration.ofMinutes(2));
ExecutionResult result = client.execution().placeOrder(terminal.id(), PlaceOrder.builder()
.symbol("EURUSD").side(Side.BUY).volume(new BigDecimal("0.10"))
.idempotencyKey("order-0001").build());
// result.ok(), result.reason(), result.brokerLatencyMs(), result.agentLatencyMs()
}POST /v1/terminals HTTP/1.1
Host: api.mfxhub.com
MFX-Key-Id: k_01J9...
MFX-Timestamp: 2026-10-20T08:12:03Z
MFX-Signature: ... # over method, path, timestamp and body hash
Idempotency-Key: first-terminal-2026-10-20
Content-Type: application/json
{"broker_id": "...", "server_id": "...", "streaming": true, "instruments": ["EURUSD"]}
HTTP/1.1 202 Accepted
{"id": "t_01J9...", "state": "REQUESTED", "conditions": []}MFX Hub against the alternatives
What you get with us, with a hosted API provider, and by running terminals yourself.
| What matters | MFX Hub | Hosted API providers | Your own VPS |
|---|---|---|---|
| Platforms | MetaTrader 5 and cTrader | Typically one platform | Whatever you install |
| Public status page, from the same per-minute record your terminals are graded on | Yes | None found | None |
| Availability commitment with service credits | Enterprise | None published; terms disclaim uninterrupted service | None |
| Support | AI assistant that reads your own terminals, email, Telegram and chat; a dedicated account manager on Enterprise | Ticket and chat | Yourself |
| Your own expert advisor, built and audited before it runs | Yes | Not offered | Yes, unaudited |
| Idempotent writes and granular rejection reasons | Every write; return code, text, reason and raw comment | Not documented | Your own |
| Broker latency and platform latency on every result | Yes, separately | Not documented | Unknown |
| Copy trading | Yes, co-located with your terminals | Yes | Build it |
| Trading analytics | Yes | Yes | Build it |
| Risk rules enforced on the terminal | Yes | Yes | Build it |
| SDKs | Python, TypeScript, .NET and Java | One to three languages | None |
| Regions | Seven, chosen for broker proximity | Several | Where your VPS is |
| Pricing | Per terminal per month | Per account per hour, typically | VM cost plus your time |
The provider column summarises the public documentation of hosted trading-API services as read in October 2026. "Not documented" means we found nothing there.
Your advisor, built and audited on your behalf
Most platforms will not run your code at all. We do, and we check it first: for your protection and for everyone else's on the same infrastructure.
We build it, so we can read it
You upload source; a compiled file cannot be audited. The build is ours, reproducible, and tied to the hash that runs.
Analysed before anything runs
Credentials and tokens in the code, external endpoints, interface calls, unbounded loops and recursion, handle growth, known malicious patterns.
A report you can act on
Five categories, four colours. Green and grey deploy automatically. Amber is read by a person with an AI assessment beside it. Red comes back to you with the reasons.
Policy you can see
The rules and their colours are a published policy with a version, so a verdict is explainable, not a mood.
Trial, then live
A trial on one terminal with trading on and the limits held, then live, with your advisor's own notes streamed to you and to nobody else.
Contained while it runs
A least-privilege account, processor and memory held, no path to another customer, every attach and detach in the record.
Support that already knows your terminals
Every conversation starts with what the platform knows about your account: your terminals, their state, their last hour. You never explain from zero.
Self-serve
- Knowledge base with runnable samples
- AI assistant that answers from the documentation
- Community on GitHub
Assisted, with your context
- Everything in Developer
- AI assistant that reads your own terminals and incidents, signed in
- Hand-over to an engineer with the diagnosis attached
- Status page subscriptions and incident emails
Managed
- Everything in Standard
- A dedicated account manager
- An incident line, around the clock
- Shared channel with our engineers; onboarding and quarterly reviews
The assistant never acts on a terminal, never reveals another customer, and never gives trading advice. Its answers cite their source.
You see what we see
Every terminal is graded every minute. A minute nobody measured is shown grey, never green. What we publish is read from the same record our operators read.
Two figures on every result, so a slow fill is never a mystery: the broker's time and ours, side by side.
One platform, four kinds of customer
Algorithmic traders
Run your strategy from any language against your own terminal, without a VPS to patch or a terminal to babysit.
Copiers and signal services
Follow one account live and mirror its trades to many, with idempotent commands and position events on a stream.
Prop firms and brokers
Dedicated capacity in your region, your own expert advisors audited and hosted, and an availability record you can show your clients.
B2B solutionsFintech products
Add account connectivity to a portfolio app, a risk dashboard or a trade journal with a single integration.
Start with one terminal, free
A developer account gives you one terminal on a demo server for 24 hours, with the full API and SDK.