API reference
Read your accounts and trades, and submit signals, from your own tools. Everything below is available on the Forex Elite add-on.
Forex by default, crypto on request. Every endpoint
returns forex only unless you ask otherwise — add
?type=crypto or ?type=all. The default is
deliberate so existing integrations keep the exact responses they
already had.
Outgoing webhooks fire for both. Each close event carries
trading_type so you can tell them apart. Crypto events
are queued and delivered within a few minutes rather than
immediately — the crypto close path runs inside trade execution and
must never wait on your endpoint.
Get a key
Go to Settings → Forex → Elite power-user hooks, name a key, and press Create key.
The secret is shown once, at creation. We store only a hash and cannot show or recover it later — if you lose it, revoke the key and create another.
Create one key per bot or script. Each is revoked independently, so retiring one integration never breaks the others.
Authentication
Send your key in the X-Api-Token header:
curl https://www.signalcopier.io/api/v1/forex/api/accounts \ -H "X-Api-Token: scp_your_key_here"
A logged-in browser session (Bearer JWT) also works and is never scope-narrowed — it is you, in your own dashboard. API keys are the credential to use for anything automated, because they carry permissions and can be revoked on their own.
Endpoints
Base URL: https://www.signalcopier.io
| Endpoint | Permission | What it does |
|---|---|---|
GET /api/v1/forex/api/accounts |
trades:read |
Your forex accounts and their connection state |
GET /api/v1/forex/api/trades |
trades:read |
Trades. Filter with ?status=closed, &pair=EURUSD, &days=7 |
POST /api/v1/forex/api/signals |
trades:write |
Submit a signal for execution |
Submitting signals
Send free text or fields — whichever your tool already produces. Text is read by the same AI that reads your Discord and Telegram signals, so you do not have to reshape anything.
POST /api/v1/forex/api/signals
X-Api-Token: scp_your_key_here
Content-Type: application/json
{"text": "BUY EURUSD @ 1.0850 SL 1.0800 TP 1.0950"}
— or structured —
{"pair": "EURUSD", "action": "buy",
"entry": 1.0850, "sl": 1.0800, "tp": 1.0950}
A successful submission returns:
{"accepted": true, "submitted": true}
“submitted”, not “filled”. It means the signal reached
your execution pipeline. Poll
GET /api/v1/forex/api/trades for the outcome.
Permissions
Every key carries its own permissions, and they are enforced on each request — a read-only key cannot place a trade, and a write-only key cannot read your history. Give each integration the narrowest set it needs.
| Permission | Grants |
|---|---|
| Loading… | |
A key with no permissions specified is created read-only. Administrative scopes are not available to customer keys.
Rate limits
Two independent limits apply, and both are enforced:
| Limit | Elite | Window |
|---|---|---|
| Loading… | ||
Exceeding either returns 429. Check your current usage at
GET /api/v1/rate-limit/usage.
The TradingView webhook is deliberately
exempt from the 429: TradingView disables an alert that
keeps receiving errors, which would cost you every future signal rather
than just the throttled one. It accepts and records instead.
Errors
| Code | Meaning | What to do |
|---|---|---|
400 | Bad request, or a permission you cannot grant | Check the response body |
401 | Missing, unknown, revoked or expired key | Create a new key |
403 | Key lacks the required permission | Use a key with that scope |
429 | Rate limit reached | Back off; see limits |
503 | No forex account connected yet | Connect an account, then retry |
A refused scope tells you exactly which one was needed:
{"error": "insufficient_scope",
"accepted": false,
"required": "trades:write"}
Outgoing webhooks
The reverse direction: instead of you calling us, we call you. Every time one of your forex trades closes we POST a small JSON body to a URL you control — so you can log to a spreadsheet, post to Slack, or update your own dashboard without polling the API.
Turn it on in Settings → Forex → Elite power-user hooks by pasting your URL. Leave it empty to disable.
What we send
POST https://your-endpoint.example.com
Content-Type: application/json
{"schema_version": 2,
"trade_id": "…", "account": "FTMO 100K",
"pair": "EURUSD", "direction": "long",
"entry_price": 1.0850, "exit_price": 1.0950,
"exit_reason": "take_profit",
"pnl_usdt": 42.50, "net_pnl_usdt": 41.20,
"opened_at": "2026-08-17T09:14:03",
"closed_at": "2026-08-17T11:02:47",
"channel_name": "…", "channel_id": "…",
"is_paper": false, "trading_type": "forex"}
| Field | Meaning |
|---|---|
schema_version | Currently 2. Only bumped on a rename or removal — new keys can appear without it, so ignore ones you do not know |
trade_id, account | Which trade, on which of your accounts |
pair, direction | Instrument and side (long / short) |
entry_price, exit_price | Fill prices |
exit_reason | Why it closed — take profit, stop loss, manual, and so on |
pnl_usdt, net_pnl_usdt | Gross and after costs, negative for a loss |
opened_at, closed_at | UTC timestamps |
channel_name, channel_id | The signal source, when the trade came from one |
is_paper | true for audition / paper trades. Off by default — enable it in settings if you want them |
trading_type | forex or crypto |
HTTPS only, and treat the URL as a secret if your
endpoint acts on what it receives. We do not retry indefinitely —
an endpoint that is down misses that event, so do not use this as
your only record. GET /api/v1/forex/api/trades remains
the source of truth.
This fires on closes, not on opens or on signals we reject. If you need those, poll the trades endpoint.
TradingView webhook (incoming)
TradingView cannot send authentication headers, so it gets its own URL with the token embedded. Copy it from Settings → Forex and paste it into TradingView → Notifications → Webhook URL.
Send whatever your indicator produces — any text or JSON shape. Treat that URL like a password: anyone holding it can place trades on your accounts. Rotate it from the same panel to invalidate the old one.