curl --request POST \
--url https://testnet.edel-api.xyz/v1/accounts/{accountId}/promo-code \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"code": "PROMODEMO"
}
'import requests
url = "https://testnet.edel-api.xyz/v1/accounts/{accountId}/promo-code"
payload = { "code": "PROMODEMO" }
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({code: 'PROMODEMO'})
};
fetch('https://testnet.edel-api.xyz/v1/accounts/{accountId}/promo-code', 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}/promo-code",
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([
'code' => 'PROMODEMO'
]),
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}/promo-code"
payload := strings.NewReader("{\n \"code\": \"PROMODEMO\"\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}/promo-code")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"code\": \"PROMODEMO\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://testnet.edel-api.xyz/v1/accounts/{accountId}/promo-code")
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 \"code\": \"PROMODEMO\"\n}"
response = http.request(request)
puts response.read_body{
"code": "<string>",
"accountId": "<string>",
"revision": 123,
"shareBps": 5000,
"perAccountCapAtoms": "<string>",
"redemptionJournalSequence": 4503599627370495,
"redeemedAtEpochMs": 1,
"windowEndEpochMs": 123
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}Redeem a promo code
Redeems one promo code for the authenticated account before its first fill. One promo per account, ever. Retrying the same code returns the original grant; a different code is refused as promo_code_already_redeemed. Redemption is ordered at its native no-fill proof; only later journal fills may qualify. Returns the share, cap and redemption window granted to the account. Codes do not reduce the trading fee at order placement; eligible fees back are settled separately. Refuses with promo_code_unknown, promo_code_expired, promo_code_exhausted, account_not_eligible or promo_code_already_redeemed. Requires the owner’s session or an owner-approved API key with the trade scope.
Method and path: POST /v1/accounts//promo-code
Authentication: DFNS trader bearer required.
Request schema: RedeemPromoCodeRequest.
Response schema: PromoCodeRedemption.
Error envelope: ExternalRestError (external-rest-error/v1).
curl --request POST \
--url https://testnet.edel-api.xyz/v1/accounts/{accountId}/promo-code \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"code": "PROMODEMO"
}
'import requests
url = "https://testnet.edel-api.xyz/v1/accounts/{accountId}/promo-code"
payload = { "code": "PROMODEMO" }
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({code: 'PROMODEMO'})
};
fetch('https://testnet.edel-api.xyz/v1/accounts/{accountId}/promo-code', 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}/promo-code",
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([
'code' => 'PROMODEMO'
]),
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}/promo-code"
payload := strings.NewReader("{\n \"code\": \"PROMODEMO\"\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}/promo-code")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"code\": \"PROMODEMO\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://testnet.edel-api.xyz/v1/accounts/{accountId}/promo-code")
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 \"code\": \"PROMODEMO\"\n}"
response = http.request(request)
puts response.read_body{
"code": "<string>",
"accountId": "<string>",
"revision": 123,
"shareBps": 5000,
"perAccountCapAtoms": "<string>",
"redemptionJournalSequence": 4503599627370495,
"redeemedAtEpochMs": 1,
"windowEndEpochMs": 123
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}{
"version": "external-rest-error/v1",
"requestId": "<string>",
"code": "promo_code_unknown",
"safeMessage": "<string>",
"retryable": true,
"recoveryActions": [
"none"
],
"occurredAtEpochMs": 1,
"orderOutcome": "not_submitted",
"clientOrderIds": [
"<string>"
],
"reconciliation": "<string>",
"realtimeTicketFailure": "invalid",
"apiKeyRejection": "malformed",
"agentRefusal": "agents_not_admitted_in_environment",
"rejectionGuard": "custodial_signer_environment_not_service_held",
"withdrawalFailure": "requested",
"feeShareAcceptRefusal": "challenge_missing",
"dependency": "dfns",
"squidRouteRefusal": "route_not_found"
}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. When invitation-only access is enabled, private operations require the account's sign-in email to be invited. Sign-in can complete without an invitation, but private HTTP, MCP and FIX operations refuse with access_not_allowlisted (HTTP 403): "Private access is limited to invited accounts. Contact support to request access." Public market data remains available. Invitation changes apply to the next private operation, including existing FIX sessions. Do not retry until support confirms access.
Path Parameters
1Body
^[A-Z0-9][A-Z0-9_-]{2,31}$Response
Success
^[A-Z0-9][A-Z0-9_-]{2,31}$10 <= x <= 10000^[1-9][0-9]{0,37}$0 <= x <= 9007199254740991x >= 0