curl --request POST \
--url https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"text": "Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back."
}
'import requests
url = "https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine"
payload = { "text": "Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back." }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
text: 'Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back.'
})
};
fetch('https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine', 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/pine",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'text' => 'Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back.'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine"
payload := strings.NewReader("{\n \"text\": \"Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back.\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"text\": \"Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back.\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"text\": \"Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back.\"\n}"
response = http.request(request)
puts response.read_body{
"pine": "<string>",
"valid": true,
"errors": [
"<string>"
],
"refusalReason": "grid_orders",
"model": {
"modelId": "<string>",
"version": "<string>",
"dataPolicy": "in_network",
"fallbackUsed": true,
"primaryFailure": "model_unknown"
}
}{
"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"
}Draft a Pine strategy from plain English
Drafts a Pine v5 strategy from a plain English description, in the subset agents run, and validates the draft with the same parser the create route uses. The answer is text for you to read: nothing is deployed. valid is true only when the parser accepts pine; otherwise errors holds the parser messages. When the description needs something outside the subset (grid or DCA orders, TWAP execution, position state, several markets or timeframes, time filters, an unsupported built-in), pine is null and refusalReason names why. A draft can take up to 90 seconds. Each account has one draft in progress at a time and at most 10 drafts per minute; past either limit the route answers 429 rate_limited with a Retry-After header, in seconds. A busy or unreachable assistant answers 503 service_degraded; retry later. Requires the owner’s passkey session or an API key with the agents scope, which the owner grants with a passkey on the agent connect approval page. Available on TestNet and Development only.
Method and path: POST /v1/accounts//agents/pine
Authentication: DFNS trader bearer required.
Request schema: TranslateAgentPineRequest.
Response schema: AgentPineTranslation.
Error envelope: ExternalRestError (external-rest-error/v1).
curl --request POST \
--url https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"text": "Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back."
}
'import requests
url = "https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine"
payload = { "text": "Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back." }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
text: 'Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back.'
})
};
fetch('https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine', 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/pine",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'text' => 'Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back.'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine"
payload := strings.NewReader("{\n \"text\": \"Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back.\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"text\": \"Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back.\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://testnet.edel-api.xyz/v1/accounts/{accountId}/agents/pine")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"text\": \"Go long when the 10 bar SMA crosses above the 30 bar SMA, and close on the cross back.\"\n}"
response = http.request(request)
puts response.read_body{
"pine": "<string>",
"valid": true,
"errors": [
"<string>"
],
"refusalReason": "grid_orders",
"model": {
"modelId": "<string>",
"version": "<string>",
"dataPolicy": "in_network",
"fallbackUsed": true,
"primaryFailure": "model_unknown"
}
}{
"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
1Body
The strategy in plain English: 1 to 4000 characters (Unicode code points) after trimming. A longer text answers 400.
11 - 64The model that drafts, from the venue's model catalog. Omitted: the catalog's default drafting model. A model the catalog does not hold for drafting answers 400.
^[a-z0-9][a-z0-9._-]{0,63}$Response
Success
grid_orders, dca_schedule, twap_execution, position_state, unsupported_builtin, multi_timeframe, multi_symbol, time_filter, outside_subset The model that answered: its id, version and data policy (in_network stays on Edel's infrastructure, third_party leaves for a vendor), and whether a declared fallback answered.
Show child attributes
Show child attributes