curl --request GET \
--url https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision \
--header 'Authorization: Bearer <token>'import requests
url = "https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"version": "agent-fill-decision/v1",
"deploymentId": "<string>",
"marketId": "<string>",
"fill": {
"tradeId": "<string>",
"orderId": "<string>",
"side": "buy",
"role": "maker",
"priceAtoms": "<string>",
"sizeAtoms": "<string>",
"recordedAtEpochMs": 123,
"origin": "liquidation"
},
"basis": "strategy_signal",
"explanation": "<string>",
"decision": {
"intentId": "<string>",
"clientOrderId": "<string>",
"decisionReason": "strategy_rule_matched",
"barTime": 1,
"decidedAtEpochMs": 123,
"signal": {
"id": "<string>",
"barIndex": 1,
"action": "entry",
"side": "long",
"qty": 123,
"fromEntry": "<string>",
"stop": 123,
"limit": 123,
"profit": 123,
"loss": 123
},
"evidence": {
"ruleValues": [
{
"name": "<string>",
"value": "<string>",
"previous": "<string>"
}
],
"indicators": [
{
"name": "<string>",
"line": 1,
"column": 1,
"value": "<string>",
"previous": "<string>"
}
],
"omittedRuleValues": 1,
"omittedIndicators": 1
},
"exitPrices": {
"entryPriceAtoms": "<string>",
"markPriceAtoms": "<string>"
},
"gate": {
"verdict": "allow",
"probability": 0.5,
"threshold": 0,
"model": {
"modelId": "<string>",
"version": "<string>"
}
},
"skill": {
"skillId": "kill_switch",
"verdict": "allow",
"reason": "skill_kill_switch_engaged",
"requestedSizeAtoms": "<string>",
"sizeAtoms": "<string>"
},
"reduceOnly": true,
"notionalAtoms": "<string>"
}
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}Ask an agent why it made one trade
Returns why the agent’s live fill with this trade id happened, read from the agent’s own action log: the fill, the order it filled and the decision that sent that order. basis is strategy_signal when the strategy’s rule fired on a closed bar (with the rule values and indicators it saw, the decision model’s verdict on an entry and what a risk skill changed), skill_exit when the stop loss or take profit closed the position, owner_close when the owner closed the paused agent’s position, venue_order when the venue placed the order (liquidation or deleveraging) and not_linked when the log holds no decision for the order. explanation is one plain sentence built from those facts; the answer is the same every time and no model writes it. 404 with not_found until the fill is in the agent’s log, which follows the fill by moments. Requires the owner’s passkey session or an API key with the agents scope. Available on TestNet and Development only.
Method and path: GET /v1/accounts//agents//fills//decision
Authentication: DFNS trader bearer required.
Request schema: none.
Response schema: AgentFillDecisionResponse.
Error envelope: ExternalRestError (external-rest-error/v1).
curl --request GET \
--url https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision \
--header 'Authorization: Bearer <token>'import requests
url = "https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/{deploymentId}/fills/{tradeId}/decision")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"version": "agent-fill-decision/v1",
"deploymentId": "<string>",
"marketId": "<string>",
"fill": {
"tradeId": "<string>",
"orderId": "<string>",
"side": "buy",
"role": "maker",
"priceAtoms": "<string>",
"sizeAtoms": "<string>",
"recordedAtEpochMs": 123,
"origin": "liquidation"
},
"basis": "strategy_signal",
"explanation": "<string>",
"decision": {
"intentId": "<string>",
"clientOrderId": "<string>",
"decisionReason": "strategy_rule_matched",
"barTime": 1,
"decidedAtEpochMs": 123,
"signal": {
"id": "<string>",
"barIndex": 1,
"action": "entry",
"side": "long",
"qty": 123,
"fromEntry": "<string>",
"stop": 123,
"limit": 123,
"profit": 123,
"loss": 123
},
"evidence": {
"ruleValues": [
{
"name": "<string>",
"value": "<string>",
"previous": "<string>"
}
],
"indicators": [
{
"name": "<string>",
"line": 1,
"column": 1,
"value": "<string>",
"previous": "<string>"
}
],
"omittedRuleValues": 1,
"omittedIndicators": 1
},
"exitPrices": {
"entryPriceAtoms": "<string>",
"markPriceAtoms": "<string>"
},
"gate": {
"verdict": "allow",
"probability": 0.5,
"threshold": 0,
"model": {
"modelId": "<string>",
"version": "<string>"
}
},
"skill": {
"skillId": "kill_switch",
"verdict": "allow",
"reason": "skill_kill_switch_engaged",
"requestedSizeAtoms": "<string>",
"sizeAtoms": "<string>"
},
"reduceOnly": true,
"notionalAtoms": "<string>"
}
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "invalid_request",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "amount_atoms_invalid",
"withdrawalFailure": "requested",
"dependency": "dfns"
}Authorizations
The authorization field takes the session bearer returned by sign-in, or an API key where the route allows keys. Paste the token itself into the authorization field.
Path Parameters
11 - 64The fill's trade id, as account.fills carries it.
1 - 128Response
Success
"agent-fill-decision/v1"^agt_[0-9a-f]{32}$1Show child attributes
Show child attributes
strategy_signal, skill_exit, owner_close, venue_order, not_linked, decision_mismatch, decision_malformed One plain sentence built from the recorded decision, the same every time.
1The recorded decision behind the order; null when no agent decision sent it.
Show child attributes
Show child attributes