API ReferenceExecution
Report the outcome of a triggered conditional order
const url = 'https://exec.predictefy.com/v1/exec/conditional/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/report';const options = { method: 'POST', headers: { 'Idempotency-Key': 'example', Authorization: 'Bearer <token>', 'Content-Type': 'application/json' }, body: '{"outcome":"fired","executionId":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","venueRef":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://exec.predictefy.com/v1/exec/conditional/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/report \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: example' \ --data '{ "outcome": "fired", "executionId": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "venueRef": "example" }'Requires Authorization: Bearer <api-key> with the trade scope and a unique Idempotency-Key. Client mode only: after conditional.triggered you act with your own credentials, then report what happened so the order's trail is complete. Only a triggered client-mode order accepts a report. An expired client attempt can also report not_submitted when its own outstanding marker and execution binding prove ownership.
outcome: fired (the default) reports which execution your submission became and moves the order to fired. outcome: not_submitted reports that the venue never accepted it and moves the order to fire_failed, leaving executionId as armed — send neither executionId nor venueRef with it. Reporting is how you close an order that can no longer be canceled because a reservation was taken for its execution.
not_submitted cannot release another attempt's reservation or clear its marker. A sibling with an outstanding marker or unreturned token returns 409 CONDITIONAL_ATTEMPT_CONFLICT, with no release or marker change. The owning attempt can still acknowledge its existing token or return its own unused token. After that return, an already re-armed and triggered sibling can reserve and bind itself.
not_submitted is refused with CONDITIONAL_NOT_ARMED on EVIDENCE, never on the linked execution's status word: when that execution carries a reference the VENUE ITSELF issued (venueRef, whatever its status reads now), when a relay is in flight or acknowledged (submitted, acked, filled), or when a reservation for it was consumed. Report fired in that case — the platform's own record contradicts the claim that nothing reached the venue. It is accepted everywhere else: an execution still built, and a signed, failed, canceled or expired execution that never earned a venue reference (a venue business rejection has exactly that shape). A REFUSAL never earns a reference on any lane — neither a digest the server derived from the order before sending it nor an identifier the venue's own error body echoes back is recorded in venueRef. Only an order the venue took records one. That holds in EITHER encoding a refusal arrives in: an error status, or a 200 carrying the rejection in band (Polymarket's and XO's success: false, Opinion's non-zero errno, PRED's failed state, Myriad's rejected state, PredictStreet's REJECTED state, Kalshi's rejected and failed states, Novig's REJECTED state). Kalshi is the one DEFENSIVE entry in that list: its published contract lists no rejected or failed order state, so the lane maps both in case one ever arrives, and the rule applies if it does. It holds whoever MINTED the identifier: a digest the server derived before sending and an id the venue itself issued for an order it then refused are equally worthless, because neither names an order resting on the book. A refused CANCEL records none either, in either encoding. A refusal records no venue identifier as a REFERENCE: neither is written to venueRef, which stays null. The execution's error carries the venue's own rejection reason, sanitized as every venue reason is, and where the venue's own sentence names its identifier that sentence is kept as the venue wrote it. This fence reads venueRef, never error, so an identifier sitting inside a reason changes nothing here. The reference separates the two events wherever they are read: a failed execution that DOES carry one failed AFTER the venue accepted the order — this fence refuses not_submitted for it and asks you to report fired, and its error says the failure followed acceptance rather than calling it a rejection.
A RELAY-LESS lane is the exception, and today that is Rain: its submit verifies the transaction the CUSTOMER signed and records the hash derived from those same bytes, with no venue call at all, so that venueRef is the customer's own artifact and never refuses the report. Be plain about what that means TODAY: Predictefy holds no on-chain observation of its own. A relay-less execution stops at signed and NO production path advances it — both the background reconciler and the status refresh write only submitted and acked rows — so a not_submitted report on Rain is accepted on the customer's word alone and recorded as theirs. The acked/filled refusal is kept for the day an observer writes those states; no writer produces them on a relay-less lane now. Predict.fun's on-chain cancel path derives a hash the same way, but its order and cancel relays reach the venue and record the venue's own order id, so Predict.fun is treated as the relay venue it is.
An accepted not_submitted closes its own conditional attempt and releases its live, unconsumed reservations. Acknowledging a returned token answers CONDITIONAL_CLOSED_NOT_SUBMITTED. A re-armed sibling's validated token remains usable after that sibling reports fired or expires, including idempotent acknowledgment replay. Ownership follows the protected execution binding or token issuance tenure, so a closed sibling does not revoke the owner's token. Reserve and submit remain fenced unless a later client attempt has triggered. A retry of a report that already committed replays even if a submission was recorded afterwards.
Safe to retry. If a report commits and you never see its response, repeating it with the same outcome (and, for fired, the same executionId and venueRef, or none) returns 200 with Idempotency-Replay: true and adds no second entry to the trail. Reporting a different execution, a different venueRef, or a different outcome is a different claim about what happened, and answers CONDITIONAL_NOT_ARMED.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Conditional (take-profit / stop-loss) order id.
Header Parameters
Section titled “Header Parameters”Caller-generated non-empty key. Build/cancel/modify keys identify newly persisted intents; a submit key identifies that relay attempt and cannot be rebound to another ID. The literal strings undefined and null are rejected with 400 VALIDATION_ERROR, so a client that stringified a missing key cannot bind or replay one. Two prefixes are RESERVED by the execution service for keys it mints itself and are rejected with 400 RESERVED_IDEMPOTENCY_KEY before anything is written: cond: (a hosted conditional order's own fire key) and dry-run: (the preview key handed to a venue lane). The match is case-sensitive.
Request Body
Section titled “Request Body”object
What happened after the trigger. fired (the default) means you submitted and the order is now live or filled. not_submitted means the venue never accepted it — the order settles fire_failed, and neither executionId nor venueRef may be sent with it, because there is no submission to point at. It is refused on EVIDENCE the venue left on that execution — a reference the venue itself issued, a relay in flight or acknowledged, or a consumed reservation — and never on the status word alone. On a relay-less lane the recorded reference is the customer's own transaction hash, so only an observed status refuses them there. An accepted one releases every live reservation on the execution and closes it off to any later reserve, submit or ack.
The execution you submitted with your own credentials. Defaults to the armed one.
The venue's order id, recorded on the conditional order's event trail.
Responses
Section titled “Responses”The conditional order, now fired or — for outcome: not_submitted — fire_failed. A retry of the same report replays it and sets Idempotency-Replay: true.
object
An armed take-profit / stop-loss order. The stored artifact, its hash, its key id and any fire lease are deliberately absent from this shape and are never returned.
object
The trusted-edge country at arm time, re-applied to the venue geofence at fire.
Present on the single-order read only.
One append-only transition, with the evidence that caused it.
object
The trigger rule. Every optional field has an engine default that is stored explicitly on the armed row, so an order always says exactly what it meant.
object
The direction the reference price must cross.
The probability the reference must reach.
mark is the median of best bid, best ask and a fresh last trade; bid/ask select the executable side explicitly.
Consecutive qualifying samples required before the order triggers.
How long the condition must hold, measured on book timestamps.
No trigger while the book's spread is wider than this.
The qualifying quote must show at least this size.
Sugar. Rewritten to when from the stored order's side (a stop sells below and buys above; take-profit mirrors it), and echoed back on the stored rule.
Example
{ "success": true, "data": { "events": [ { "actor": "api" } ], "fireMode": "hosted", "status": "armed", "trigger": { "when": "at_or_above", "reference": "mark", "confirmations": 2, "dwellMs": 2000, "maxSpread": 0.1, "minSize": 1, "tpsl": "tp" } }}Headers
Section titled “Headers”Present with value true when stored state satisfied an idempotent retry.
A missing or RESERVED Idempotency-Key, or an invalid request/body/lifecycle state.
object
object
Always present on errors; quote this id when reporting a failed request.
Present only when a venue error is attributed to a specific exchange.
Example
{ "success": false, "error": { "code": "VALIDATION_ERROR" }}Missing, invalid, unknown, or revoked Predictefy API key.
object
object
Always present on errors; quote this id when reporting a failed request.
Present only when a venue error is attributed to a specific exchange.
Example
{ "success": false, "error": { "code": "VALIDATION_ERROR" }}The API key lacks the mandatory trade scope, or the account's plan does not include conditional orders (Pro is the minimum).
object
object
Always present on errors; quote this id when reporting a failed request.
Present only when a venue error is attributed to a specific exchange.
Example
{ "success": false, "error": { "code": "VALIDATION_ERROR" }}The conditional order or the reported execution is missing or not owned by the caller, or the family is not enabled for this account.
object
object
Always present on errors; quote this id when reporting a failed request.
Present only when a venue error is attributed to a specific exchange.
Example
{ "success": false, "error": { "code": "VALIDATION_ERROR" }}The conditional order has already left the state this change requires — a trigger, expiry, or cancel landed first. Cancel also returns CONDITIONAL_NOT_ARMED for a triggered client order whose linked execution is no longer built, or that carries a reservation you could still be acting on — a live one, a consumed one however old, or any taken since the order was armed — checked under its execution row lock. A reservation hands the caller a token to submit with, and that submission never passes through this API, so the order stays triggered and can no longer be canceled: use /v1/exec/conditional/{id}/report to report the outcome instead — that route decides which outcomes it accepts for the state the execution is actually in. A reservation that predates the arm and has already lapsed does not fence. A sibling attempt that still owns an outstanding marker or unreturned token refuses not_submitted with CONDITIONAL_ATTEMPT_CONFLICT. Nothing is released or cleared. New reservation issuance and ordinary submission also return this code if another attempt owns the outstanding marker. Tokens already issued remain acknowledgeable.
object
object
Always present on errors; quote this id when reporting a failed request.
Present only when a venue error is attributed to a specific exchange.
Example
{ "success": false, "error": { "code": "VALIDATION_ERROR" }}The authenticated execution token bucket is exhausted.
object
object
Always present on errors; quote this id when reporting a failed request.
Present only when a venue error is attributed to a specific exchange.
Example
{ "success": false, "error": { "code": "VALIDATION_ERROR" }}Unexpected internal execution failure.
object
object
Always present on errors; quote this id when reporting a failed request.
Present only when a venue error is attributed to a specific exchange.
Example
{ "success": false, "error": { "code": "VALIDATION_ERROR" }}Authentication, billing, or execution storage is temporarily unavailable.
object
object
Always present on errors; quote this id when reporting a failed request.
Present only when a venue error is attributed to a specific exchange.
Example
{ "success": false, "error": { "code": "VALIDATION_ERROR" }}