Retries, duplicates and command ids
How long a paper command id is protected against a second execution (30 days), why a record can be re-stamped, what happens after retirement, and how to repeat an action on purpose.
When the same instruction reaches a NixoraPaper account twice, the account has to decide whether you meant it once or twice. This lesson is the rule it uses, how long that rule lasts, and what that means for retries, double-fired alerts and anything you send from your own code.
It is about NixoraPaper accounts. A live broker account has its own duplicate protection, and nothing on this page puts a 30-day figure on it.
Retry deduplication, not exactly-once
Retries using the same immutable command id are deduplicated within the supported retention window. That is the whole promise, and it is a promise about retries. It is not an absolute exactly-once promise.
- Covered: a retry, a network repeat or a double-fired alert that carries the same id inside the window. It is recognised as a duplicate and answered with the original result, with no second effect.
- Not covered: a command sent with a different id (that is a different command), an alert with no id on a NixoraPaper account once its 15-second match has passed, and the same id after the window has ended and the record has been retired. Each of those can execute.
For a paper account the window is 30 days, described next. No claim of "never twice" or "for ever" is made anywhere in this guide, and the Site does not advertise one.
The 30-day rule
Duplicate protection for a paper command lasts 30 days. A command that carries an id is protected over the
window from the moment its record was last stamped until 30 days after that moment. Inside the window,
sending the same id again changes nothing: you get the original result back, marked duplicate: true. Once
the window has passed and the record has been retired, the id is no longer protected, and a command sent with
that id is a new command and executes.
day 0 day 29 day 30 (window ends) later
|-----------|-----------|------------------------>
same id = duplicate record retired at the next touch;
(original result) the same id may then execute again
Three things follow, and they are the whole contract:
- A retry with the same id inside the window is deduplicated. It does not place a second order. That is a statement about retries of one command, not an exactly-once promise for everything you might send.
- Nothing on our side replays a command after 30 days. No Nixora queue, outbox, recovery path or automatic retry re-sends an old command. The longest automatic replay age is zero.
- After 30 days, only you can cause a repeat. If a sender outside Nixora re-fires the same id, it is treated as a fresh instruction. See When an old id comes back.
Which commands carry an id
The rule applies to every paper command that has an id:
- An action taken in the app. The app gives each action its own id. If you repeat the same action because you never saw the result, the app reuses the id for a short time so the retry is a duplicate.
- A webhook alert that includes an
id. The id you write in the message is the identity. - A strategy alert. The identity is worked out from the alert's own id, so the same alert is the same command each time.
An alert with no id is different. It is recognised only by its exact bytes, and on a NixoraPaper account
only for 15 seconds. The same message sent a minute later is a second instruction, not a duplicate. If you
want protection that lasts, put a short id in the message.
{"action":"open","side":"buy","symbol":"EURUSD","vol_lots":0.5,"id":"lfvg-{{time}}"}
A refused command is never replayed. If an account refuses an order because it had no usable quote, then sending it again decides it again, and it may be accepted this time.
Live broker accounts: always send a short unique ID
The windows described above are how a NixoraPaper account behaves. A live broker account has its own duplicate protection, and this guide gives no duration for it. What you can rely on is the id you send:
Without an explicit ID, duplicate protection may cover only alerts received in the same clock second. Always send a short unique ID.
Two rules make that work on every kind of account: the id must be different for every real signal, and it must be short and plain, as the next section explains.
Keep the id short and plain: under 28 characters
Keep alert id values under 28 characters, and use only letters, digits and _ . : -. Spaces, slashes and
other symbols can be removed from the id before it is compared.
This is a compatibility limit. Some supported secondary MetaTrader connections carry only the first 28 characters of an id. If two long ids start the same way, they become the same id after the cut, and the second real signal is treated as a repeat of the first and swallowed. Short ids cannot collide that way.
{{time}} is filled in by TradingView with 20 characters, for example 2026-10-04T08:00:00Z. That leaves
at most 7 characters for a label and its dash. A label of london-fvg plus {{time}} is 31 characters and is too
long. A four-letter label is safe:
{"action":"open","side":"buy","symbol":"EURUSD","vol_lots":0.5,"id":"lfvg-{{time}}"}
{"action":"open","side":"buy","symbol":"EURUSD","vol_lots":0.5,"id":"lfvg-0930a"}
The first id is 25 characters once TradingView fills in the time. The second is 10. If you use {{ticker}} in an id
it adds the ticker's own length, so keep tickers to six characters (EURUSD fits) or use a short label instead.
Why the window can be longer than 30 days
The 30 days are counted from when the record was last stamped, not from the first time you sent the command. A record is not stamped once and then left alone: it can be stamped again.
The common case is an OCO pair. When one order of the pair fills, the account cancels its sibling, and that cancellation reuses the sibling's command id. That re-stamps the sibling's record at fill time, so its window starts again from then.
Re-stamping can only lengthen the protection. It never shortens it. You do not need to do anything about it; it is why you should not assume a command's window ended exactly 30 days after you first sent it.
What happens when the window ends
The protected window ends at 30 days after the last stamp, but the record is not removed at that exact second. It is retired the next time the account does ordinary work that is not itself a duplicate.
- An active account retires expired records in the same day. Typically that is within about 15 hours of the window ending.
- An idle account retires them at its next real activity.
- A stream of duplicate retries does not trigger retirement. A duplicate answer returns before the clean-up runs, so an expired record keeps answering as a duplicate until something else touches the account. This errs on the safe side: protection is never cut short.
After retirement, sending the same id again is outside the guarantee and may execute again as a new command. A reset of the account starts a new generation, and ids used before the reset are not carried over.
When an old id comes back
Nixora never sends an old command again by itself. The case that matters is a sender outside Nixora that uses the same id for every fire.
A TradingView alert whose message has a fixed id, for example "id":"london-fvg", sends that same id each
time it triggers. On a NixoraPaper account, in the first 30 days the second fire is answered as a duplicate. A fire after the record has
been retired is a new command, and it executes. That is correct if you meant it, and a surprise if you did not.
Two rules keep this simple:
- Never reuse an id for a different intent. An id names one decision, not one strategy.
- To repeat an action on purpose, send a new id. Put something in the id that changes each time, such as the bar time, so each real signal is its own command.
{"action":"open","side":"buy","symbol":"EURUSD","vol_lots":0.5,"id":"lfvg-{{time}}"}
If you would rather have a repeat blocked than executed, do not rely on an old id to do it. Remove the fixed id from the alert, or switch the alert off in TradingView.
The exact rule, for API consumers
This section is the precise form of the contract, for code that sends commands to the paper API.
| Term | Meaning |
|---|---|
commandId / webhook id |
The identity of one command. Reused verbatim, so the same value is the same command. |
at |
The time the command's idempotency record was last stamped. A later event with the same id stamps it again. |
| Protected window | The half-open interval [at, at + 30 days). |
duplicate: true |
The reply for a repeated id: the original result, no new effect. |
Before
at + 30 daysa repeated id is always a duplicate.At or after
at + 30 daysit is a duplicate only until a retirement step has removed the record. That step runs on the next non-duplicate touch of the account, typically within about 15 hours on an active account, and at the next activity on an idle one. After that it executes as a new command.Re-stamping lengthens the window. It does not shorten it, so a command is not stamped once and for all.
A refused command is not stored as a duplicate. Sending it again decides it again.
No id on a webhook alert to a NixoraPaper account means a 15 second window on the exact body, not 30 days.
Scope of the guarantee: retry deduplication of one immutable command id within the retention window. It is not an absolute exactly-once promise; a different id, or the same id after retirement, is a new command.
Client guidance: treat a response of duplicate: true as success of the original command. Do not retry the
same id after 30 days expecting it to be refused. If a command must run again, use a new id.
Related: What NixoraPaper does not simulate · Keyword reference.