Credit or debit a trading account
Changes one account’s balance by an amount and records it under your own reference (for example a deposit or withdrawal ID from your CRM). A positive amount credits the account, a negative one debits it.
The amount is applied to the live balance as a change, alongside any trading on the account, so it never overwrites profit or loss made at the same moment. The response gives the balance just before and just after it.
Idempotent by reference. A reference is used once per organization, permanently. Sending the same reference with the same request again returns the original adjustment with 200 and replayed: true; it is never applied twice. The same reference with a different request (another account, amount, reason, metadata or option) is refused with 409 REFERENCE_CONFLICT. The Idempotency-Key header is also accepted, as on every write.
Which accounts. Any account of your organization that is not passed, failed or expired (409 ACCOUNT_CLOSED), including accounts not started yet and accounts turned off.
Debits. A debit that would take the balance below zero is refused (422 INSUFFICIENT_BALANCE, checked against the balance when the request arrives). A debit is not checked against the account’s loss limits: the account’s rules apply to the new balance as after any balance change, so a debit that reaches the maximum loss or drawdown limit fails the account (account.failed). Check the account first (GET /organization/trading-accounts/{accountId}) when that matters.
Daily P&L and high-water mark. By default the adjustment is not counted as the day’s profit or loss and the high-water mark does not move; see countTowardDailyPnl and moveHighWaterMark.
Unconfirmed outcome. In the rare case the change cannot be confirmed in time, the call answers 503 OUTCOME_UNKNOWN with the adjustment in status pending. Send the same request again to settle it.
Webhooks. account.balance_adjusted with the adjustment (reference, amount, balances, your metadata); it is delivered only to endpoints that list it explicitly, never through ["*"]. As for every balance adjustment, the account also gets account.updated with trigger balance_adjustment, and account.balance_changed with reason adjustment for its subscribers.
Returns 201 for a new adjustment. Requires manage permission on traders.
curl -X POST "https://api.hyperprop.com/platform/v1/organization/trading-accounts/7c9e6679-7425-40de-944b-e07fc1f90ae7/balance-adjustments" \
-H "X-API-Key: hp_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"amount": 500, "reference": "DEP-2026-104233", "reason": "Deposit via card", "metadata": {"crmTransactionId": "TX-88213"}}'
curl --request POST \
--url https://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"amount": 500,
"reference": "DEP-2026-104233",
"reason": "Deposit via card",
"metadata": {
"crmTransactionId": "TX-88213",
"method": "card"
},
"countTowardDailyPnl": false,
"moveHighWaterMark": false
}
'import requests
url = "https://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments"
payload = {
"amount": 500,
"reference": "DEP-2026-104233",
"reason": "Deposit via card",
"metadata": {
"crmTransactionId": "TX-88213",
"method": "card"
},
"countTowardDailyPnl": False,
"moveHighWaterMark": False
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
amount: 500,
reference: 'DEP-2026-104233',
reason: 'Deposit via card',
metadata: {crmTransactionId: 'TX-88213', method: 'card'},
countTowardDailyPnl: false,
moveHighWaterMark: false
})
};
fetch('https://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments', 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://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments",
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([
'amount' => 500,
'reference' => 'DEP-2026-104233',
'reason' => 'Deposit via card',
'metadata' => [
'crmTransactionId' => 'TX-88213',
'method' => 'card'
],
'countTowardDailyPnl' => false,
'moveHighWaterMark' => false
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments"
payload := strings.NewReader("{\n \"amount\": 500,\n \"reference\": \"DEP-2026-104233\",\n \"reason\": \"Deposit via card\",\n \"metadata\": {\n \"crmTransactionId\": \"TX-88213\",\n \"method\": \"card\"\n },\n \"countTowardDailyPnl\": false,\n \"moveHighWaterMark\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 500,\n \"reference\": \"DEP-2026-104233\",\n \"reason\": \"Deposit via card\",\n \"metadata\": {\n \"crmTransactionId\": \"TX-88213\",\n \"method\": \"card\"\n },\n \"countTowardDailyPnl\": false,\n \"moveHighWaterMark\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": 500,\n \"reference\": \"DEP-2026-104233\",\n \"reason\": \"Deposit via card\",\n \"metadata\": {\n \"crmTransactionId\": \"TX-88213\",\n \"method\": \"card\"\n },\n \"countTowardDailyPnl\": false,\n \"moveHighWaterMark\": false\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"adjustmentId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"reference": "DEP-2026-104233",
"accountId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"accountNumber": "ACC-50K-000123",
"type": "credit",
"amount": 500,
"status": "applied",
"reason": "Deposit via card",
"metadata": {},
"countTowardDailyPnl": false,
"moveHighWaterMark": false,
"balanceBefore": 50000,
"balanceAfter": 50500,
"errorCode": null,
"errorMessage": null,
"requestedBy": "api-key",
"createdAt": "2026-10-30T11:02:11.000Z",
"appliedAt": "2026-10-30T11:02:11.412Z",
"replayed": true
}
}{
"success": true,
"data": {
"adjustmentId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"reference": "DEP-2026-104233",
"accountId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"accountNumber": "ACC-50K-000123",
"type": "credit",
"amount": 500,
"status": "applied",
"reason": "Deposit via card",
"metadata": {},
"countTowardDailyPnl": false,
"moveHighWaterMark": false,
"balanceBefore": 50000,
"balanceAfter": 50500,
"errorCode": null,
"errorMessage": null,
"requestedBy": "api-key",
"createdAt": "2026-10-30T11:02:11.000Z",
"appliedAt": "2026-10-30T11:02:11.412Z",
"replayed": false
}
}{
"success": false,
"statusCode": 400,
"error": "Bad Request",
"message": "Validation failed",
"code": "VALIDATION_ERROR"
}{
"success": false,
"statusCode": 401,
"error": "Unauthorized",
"message": "Authentication required",
"code": "UNAUTHORIZED"
}{
"statusCode": 403,
"error": "Forbidden",
"message": "Your role does not have write access to \"Traders & accounts\"",
"code": "INSUFFICIENT_PERMISSIONS"
}{
"success": false,
"statusCode": 404,
"error": "Not Found",
"message": "Trading account not found",
"code": "ACCOUNT_NOT_FOUND"
}{
"success": false,
"statusCode": 409,
"error": "Conflict",
"message": "Reference \"DEP-2026-104233\" was already used for a different adjustment; use a new reference",
"code": "REFERENCE_CONFLICT",
"adjustmentId": "<string>",
"adjustment": {
"adjustmentId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"reference": "DEP-2026-104233",
"accountId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"accountNumber": "ACC-50K-000123",
"type": "credit",
"amount": 500,
"status": "applied",
"reason": "Deposit via card",
"metadata": {},
"countTowardDailyPnl": false,
"moveHighWaterMark": false,
"balanceBefore": 50000,
"balanceAfter": 50500,
"errorCode": null,
"errorMessage": null,
"requestedBy": "api-key",
"createdAt": "2026-10-30T11:02:11.000Z",
"appliedAt": "2026-10-30T11:02:11.412Z"
}
}{
"success": false,
"statusCode": 422,
"error": "Unprocessable Entity",
"message": "A debit of 600.00 would take the balance (450.00) below zero; nothing was changed",
"code": "INSUFFICIENT_BALANCE",
"currentBalance": 450
}{
"success": false,
"statusCode": 500,
"error": "Internal Server Error",
"message": "An unexpected error occurred",
"code": "INTERNAL_ERROR"
}{
"success": false,
"statusCode": 503,
"error": "Service Unavailable",
"message": "The adjustment could not be confirmed yet. Send the same request again (same reference) to settle it; it is never applied twice.",
"code": "OUTCOME_UNKNOWN",
"adjustment": {
"adjustmentId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"reference": "DEP-2026-104233",
"accountId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"accountNumber": "ACC-50K-000123",
"type": "credit",
"amount": 500,
"status": "applied",
"reason": "Deposit via card",
"metadata": {},
"countTowardDailyPnl": false,
"moveHighWaterMark": false,
"balanceBefore": 50000,
"balanceAfter": 50500,
"errorCode": null,
"errorMessage": null,
"requestedBy": "api-key",
"createdAt": "2026-10-30T11:02:11.000Z",
"appliedAt": "2026-10-30T11:02:11.412Z"
}
}Authorizations
Organization API key. Format: "hp_live_{key}". Organization admins manage the key in the dashboard.
Path Parameters
Trading account ID
Body
Signed amount in the account currency, at most 2 decimals: positive credits the account, negative debits it. Not zero; at most 10,000,000 either way. Send a JSON number.
-10000000 <= x <= 10000000500
Your reference for this adjustment, for example your deposit or withdrawal ID: 1 to 128 characters, letters, digits and . _ : @ + = ~ -, starting with a letter or digit. Unique within your organization and case-sensitive.
^[A-Za-z0-9][A-Za-z0-9._:@+=~-]{0,127}$"DEP-2026-104233"
Shown in the account activity, the audit log and the webhook.
500"Deposit via card"
Up to 20 keys of your own (strings up to 500 characters, numbers, booleans or null), returned as sent and included in the webhook.
{
"crmTransactionId": "TX-88213",
"method": "card"
}
Default false: the day's starting balance moves with the adjustment, so it is not counted as that day's profit or loss (the daily loss limit stays where it was). true: it counts toward the day's P&L.
Default false: the high-water mark (trailing drawdown peak) stays where it is. true: it moves by the amount as well.
curl --request POST \
--url https://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"amount": 500,
"reference": "DEP-2026-104233",
"reason": "Deposit via card",
"metadata": {
"crmTransactionId": "TX-88213",
"method": "card"
},
"countTowardDailyPnl": false,
"moveHighWaterMark": false
}
'import requests
url = "https://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments"
payload = {
"amount": 500,
"reference": "DEP-2026-104233",
"reason": "Deposit via card",
"metadata": {
"crmTransactionId": "TX-88213",
"method": "card"
},
"countTowardDailyPnl": False,
"moveHighWaterMark": False
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
amount: 500,
reference: 'DEP-2026-104233',
reason: 'Deposit via card',
metadata: {crmTransactionId: 'TX-88213', method: 'card'},
countTowardDailyPnl: false,
moveHighWaterMark: false
})
};
fetch('https://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments', 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://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments",
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([
'amount' => 500,
'reference' => 'DEP-2026-104233',
'reason' => 'Deposit via card',
'metadata' => [
'crmTransactionId' => 'TX-88213',
'method' => 'card'
],
'countTowardDailyPnl' => false,
'moveHighWaterMark' => false
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments"
payload := strings.NewReader("{\n \"amount\": 500,\n \"reference\": \"DEP-2026-104233\",\n \"reason\": \"Deposit via card\",\n \"metadata\": {\n \"crmTransactionId\": \"TX-88213\",\n \"method\": \"card\"\n },\n \"countTowardDailyPnl\": false,\n \"moveHighWaterMark\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 500,\n \"reference\": \"DEP-2026-104233\",\n \"reason\": \"Deposit via card\",\n \"metadata\": {\n \"crmTransactionId\": \"TX-88213\",\n \"method\": \"card\"\n },\n \"countTowardDailyPnl\": false,\n \"moveHighWaterMark\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hyperprop.com/platform/v1/organization/trading-accounts/{accountId}/balance-adjustments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": 500,\n \"reference\": \"DEP-2026-104233\",\n \"reason\": \"Deposit via card\",\n \"metadata\": {\n \"crmTransactionId\": \"TX-88213\",\n \"method\": \"card\"\n },\n \"countTowardDailyPnl\": false,\n \"moveHighWaterMark\": false\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"adjustmentId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"reference": "DEP-2026-104233",
"accountId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"accountNumber": "ACC-50K-000123",
"type": "credit",
"amount": 500,
"status": "applied",
"reason": "Deposit via card",
"metadata": {},
"countTowardDailyPnl": false,
"moveHighWaterMark": false,
"balanceBefore": 50000,
"balanceAfter": 50500,
"errorCode": null,
"errorMessage": null,
"requestedBy": "api-key",
"createdAt": "2026-10-30T11:02:11.000Z",
"appliedAt": "2026-10-30T11:02:11.412Z",
"replayed": true
}
}{
"success": true,
"data": {
"adjustmentId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"reference": "DEP-2026-104233",
"accountId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"accountNumber": "ACC-50K-000123",
"type": "credit",
"amount": 500,
"status": "applied",
"reason": "Deposit via card",
"metadata": {},
"countTowardDailyPnl": false,
"moveHighWaterMark": false,
"balanceBefore": 50000,
"balanceAfter": 50500,
"errorCode": null,
"errorMessage": null,
"requestedBy": "api-key",
"createdAt": "2026-10-30T11:02:11.000Z",
"appliedAt": "2026-10-30T11:02:11.412Z",
"replayed": false
}
}{
"success": false,
"statusCode": 400,
"error": "Bad Request",
"message": "Validation failed",
"code": "VALIDATION_ERROR"
}{
"success": false,
"statusCode": 401,
"error": "Unauthorized",
"message": "Authentication required",
"code": "UNAUTHORIZED"
}{
"statusCode": 403,
"error": "Forbidden",
"message": "Your role does not have write access to \"Traders & accounts\"",
"code": "INSUFFICIENT_PERMISSIONS"
}{
"success": false,
"statusCode": 404,
"error": "Not Found",
"message": "Trading account not found",
"code": "ACCOUNT_NOT_FOUND"
}{
"success": false,
"statusCode": 409,
"error": "Conflict",
"message": "Reference \"DEP-2026-104233\" was already used for a different adjustment; use a new reference",
"code": "REFERENCE_CONFLICT",
"adjustmentId": "<string>",
"adjustment": {
"adjustmentId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"reference": "DEP-2026-104233",
"accountId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"accountNumber": "ACC-50K-000123",
"type": "credit",
"amount": 500,
"status": "applied",
"reason": "Deposit via card",
"metadata": {},
"countTowardDailyPnl": false,
"moveHighWaterMark": false,
"balanceBefore": 50000,
"balanceAfter": 50500,
"errorCode": null,
"errorMessage": null,
"requestedBy": "api-key",
"createdAt": "2026-10-30T11:02:11.000Z",
"appliedAt": "2026-10-30T11:02:11.412Z"
}
}{
"success": false,
"statusCode": 422,
"error": "Unprocessable Entity",
"message": "A debit of 600.00 would take the balance (450.00) below zero; nothing was changed",
"code": "INSUFFICIENT_BALANCE",
"currentBalance": 450
}{
"success": false,
"statusCode": 500,
"error": "Internal Server Error",
"message": "An unexpected error occurred",
"code": "INTERNAL_ERROR"
}{
"success": false,
"statusCode": 503,
"error": "Service Unavailable",
"message": "The adjustment could not be confirmed yet. Send the same request again (same reference) to settle it; it is never applied twice.",
"code": "OUTCOME_UNKNOWN",
"adjustment": {
"adjustmentId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"reference": "DEP-2026-104233",
"accountId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"accountNumber": "ACC-50K-000123",
"type": "credit",
"amount": 500,
"status": "applied",
"reason": "Deposit via card",
"metadata": {},
"countTowardDailyPnl": false,
"moveHighWaterMark": false,
"balanceBefore": 50000,
"balanceAfter": 50500,
"errorCode": null,
"errorMessage": null,
"requestedBy": "api-key",
"createdAt": "2026-10-30T11:02:11.000Z",
"appliedAt": "2026-10-30T11:02:11.412Z"
}
}