POST Create Cashier Deposit¶
Endpoint¶
POST /cashier/deposit
Command¶
CreateCashierDeposit
Authorization¶
Requires SESSION_CUSTOMER.
Description¶
Creates a deposit transaction for a customer-owned trading account. For an automatic method, Cashier calls the configured payment provider module. For a manual method, it creates a request for review and returns the configured receiving instructions without calling a payment module or crediting the account.
The server validates that login belongs to the authenticated customer and
that the account and account group are enabled. It also rechecks Cashier
payment method eligibility for the resolved brand/account currency/customer
country before creating the transaction. This protects the submit endpoint even
if the client did not call GetCashierMethods first.
Customer-level deposit_allowed is a hard gate. If it is 0, the endpoint
returns DEPOSIT_NOT_ALLOWED before provider eligibility is checked.
The transaction is persisted in bases/cashier.db before it is exposed in the
Cashier runtime cache. A returned created transaction is therefore backed by a
completed durable write.
For an automatic method, if the provider returns a redirect URL, the response
contains next_action = REDIRECT. Otherwise the client should wait for
provider-side completion. If the provider confirms the deposit synchronously,
Cashier submits a durable balance operation immediately; the transaction may
already be in processing_ledger, credited, or credit_failed when the
response is returned. A matching trade visible in memory is not sufficient to
finalize the Cashier transaction; the matching result must be confirmed
committed in the separate trading database. The Cashier and trading databases
do not share one atomic transaction. next_action remains based on whether the provider
returned a redirect URL, so clients should use transaction.status to detect
this immediate confirmation/ledger path. A manual deposit has status = 9 (manual_review) and
next_action = WAIT_MANUAL_REVIEW; a manager must process it before the
trading account is credited.
The endpoint does not accept owner_manager_id. The Owner of the created
transaction is the manager the customer is assigned to at that moment, and it is
returned in the transaction object. Only the manual BackOffice commands let a
manager choose it explicitly; see
Transaction Ownership.
Request Parameters¶
| Name | Type | Required | Description |
|---|---|---|---|
login |
int | Yes | Customer-owned trading account login |
provider |
string | Yes | Configured provider route code, 1–64 characters |
amount |
double | Yes | Deposit amount, must be at least 0.01 |
currency |
string | Yes | Payment currency, 1–8 characters. Currently must match the account group currency |
method |
string | No | Provider method marker, max 64 characters, for example card or bank_transfer |
provider_config_id |
int | No | 1 or greater; selects this exact eligible provider config, useful when multiple methods share provider/method values |
details |
object | No | Manual-method customer fields validated against its form_schema; omitted details are treated as {}. Automatic methods do not consume this field |
idempotency_key |
string | No | Customer-scoped duplicate detection key, max 128 characters; duplicate requests are rejected rather than replaying the prior response |
success_url |
string | No | URL passed to provider for successful payment redirects, max 2048 characters |
failure_url |
string | No | URL passed to provider for failed/cancelled payment redirects, max 2048 characters |
comment |
string | No | Customer-visible or audit comment, max 512 characters |
metadata_json |
string | No | Additional metadata JSON string. For manual deposits it must encode a JSON object and is stored inside the transaction snapshot as client_metadata |
Request Example¶
{
"login": 2000009,
"provider": "stripe",
"provider_config_id": 1,
"method": "card",
"amount": 250.0,
"currency": "USD",
"idempotency_key": "0f9bb0e7-642d-4b70-b458-62e3993c7d2d",
"success_url": "https://terminal.example.com/cashier/success",
"failure_url": "https://terminal.example.com/cashier/failure"
}
Manual deposit request example¶
Select the config returned by GET /cashier/methods?type=deposit using its
provider_config_id. provider and method must match that eligible config;
details must satisfy its form_schema.
POST /cashier/deposit
Authorization: <CUSTOMER_JWT>
Content-Type: application/json
{
"login": 2000009,
"provider": "manual",
"method": "bank_transfer",
"provider_config_id": 7,
"amount": 100.0,
"currency": "USD",
"details": {
"payer_name": "Ada Example",
"payment_reference": "dep-manual-001"
},
"idempotency_key": "dep-manual-001",
"comment": "Bank deposit"
}
Response Parameters¶
| Name | Type | Description |
|---|---|---|
transaction |
object | Created/updated Cashier transaction |
payment |
object | Provider payment creation result, or manual deposit instructions |
next_action |
string | REDIRECT, WAIT_PROVIDER_PAYMENT, or WAIT_MANUAL_REVIEW |
transaction¶
| Name | Type | Description |
|---|---|---|
id |
int | Cashier transaction id |
customer_id |
int | Customer id |
login |
int | Target trading account login |
type |
int | 0 for deposit |
provider |
string | Provider code |
method |
string | Provider method |
provider_config_id |
int | Selected brand-level provider config id |
provider_payment_id |
string | External payment id returned by provider |
amount |
double | Original payment amount |
currency |
string | Payment currency |
account_currency |
string | Trading account currency used by Cashier |
converted_amount |
double | Amount in account currency |
conversion_rate |
double | Conversion rate used by Cashier |
status |
int | Cashier transaction status |
failure_reason |
string | Failure reason when status is failed |
idempotency_key |
string | Request retry key |
comment |
string | Comment |
metadata_json |
string | Additional metadata string, or for manual deposits a JSON snapshot of the selected config, submitted details, instructions, and optional client metadata |
source |
int | 0 for automatic provider flow, 1 for manual flow |
approved_by |
int | Approving manager id; 0 before approval |
approved_time |
int64 | Approval timestamp; 0 before approval |
processed_by |
int | Processing manager id; 0 before processing |
processed_time |
int64 | Processing timestamp; 0 before processing |
reject_reason |
string | Rejection reason; empty when not rejected |
created_time |
int64 | Creation timestamp |
updated_time |
int64 | Last update timestamp |
attributed_manager_id |
int | Manager the customer was assigned to when the transaction was created |
owner_manager_id |
int | Manager assigned as transaction owner |
payment¶
| Name | Type | Description |
|---|---|---|
provider_payment_id |
string | External payment id |
redirect_url |
string | URL where the client should redirect the customer |
instructions_json |
string | Provider instructions JSON string; for manual deposits, the configured public settings_json object serialized as a string |
raw_response_json |
string | Raw provider response JSON string; {} for manual deposits |
status |
int | Normalized provider status; 1 in the manual-review response |
failure_reason |
string | Provider failure reason; empty for manual deposits |
Response Example¶
{
"transaction": {
"id": 15,
"customer_id": 5,
"login": 2000009,
"type": 0,
"provider": "stripe",
"method": "card",
"provider_config_id": 1,
"provider_payment_id": "pi_123",
"amount": 250.0,
"currency": "USD",
"account_currency": "USD",
"converted_amount": 250.0,
"conversion_rate": 1.0,
"status": 1,
"failure_reason": "",
"idempotency_key": "0f9bb0e7-642d-4b70-b458-62e3993c7d2d",
"comment": "",
"metadata_json": "{}",
"source": 0,
"approved_by": 0,
"approved_time": 0,
"processed_by": 0,
"processed_time": 0,
"reject_reason": "",
"created_time": 1779270000,
"updated_time": 1779270000,
"attributed_manager_id": 12,
"owner_manager_id": 12
},
"payment": {
"provider_payment_id": "pi_123",
"redirect_url": "https://provider.example/pay/pi_123",
"instructions_json": "{}",
"raw_response_json": "{}",
"status": 1,
"failure_reason": ""
},
"next_action": "REDIRECT"
}
Manual deposit response example¶
With execution_mode = 1, the request creates a manual review transaction and
does not call a provider module. The payment instructions are the public
settings_json object from the selected config, serialized as a JSON string in
payment.instructions_json.
{
"transaction": {
"id": 31,
"customer_id": 5,
"login": 2000009,
"type": 0,
"provider": "manual",
"method": "bank_transfer",
"provider_config_id": 7,
"provider_payment_id": "",
"amount": 100.0,
"currency": "USD",
"account_currency": "USD",
"converted_amount": 100.0,
"conversion_rate": 1.0,
"status": 9,
"failure_reason": "",
"idempotency_key": "dep-manual-001",
"comment": "Bank deposit",
"metadata_json": "{\"provider_config_id\":7,\"method\":\"bank_transfer\",\"display_name\":\"Bank transfer\",\"details\":{\"payer_name\":\"Ada Example\",\"payment_reference\":\"dep-manual-001\"},\"instructions\":{\"beneficiary\":\"Example Trading Ltd\",\"iban\":\"GB00EXAMPLE00000000000000\",\"bank_name\":\"Example Bank\",\"reference\":\"Use the reference returned with your request\"}}",
"source": 1,
"approved_by": 0,
"approved_time": 0,
"processed_by": 0,
"processed_time": 0,
"reject_reason": "",
"created_time": 1779270000,
"updated_time": 1779270000,
"attributed_manager_id": 12,
"owner_manager_id": 12
},
"payment": {
"provider_payment_id": "",
"redirect_url": "",
"instructions_json": "{\"beneficiary\":\"Example Trading Ltd\",\"iban\":\"GB00EXAMPLE00000000000000\",\"bank_name\":\"Example Bank\",\"reference\":\"Use the reference returned with your request\"}",
"raw_response_json": "{}",
"status": 1,
"failure_reason": ""
},
"next_action": "WAIT_MANUAL_REVIEW"
}
Errors¶
| HTTP | Error | Description |
|---|---|---|
400 |
INVALID_DATA |
Request validation failed |
400 |
ACCOUNT_NOT_AVAILABLE |
Account does not exist or is disabled |
400 |
GROUP_NOT_AVAILABLE |
Account group does not exist or is disabled |
400 |
CURRENCY_CONVERSION_REQUIRED |
Requested currency differs from account currency and conversion is not supported yet |
400 |
INVALID_DEPOSIT_DETAILS |
details does not match the selected manual method's form_schema |
400 |
INVALID_PAYMENT_INSTRUCTIONS |
Manual method settings_json is unavailable or is not a JSON object |
400 |
INVALID_METADATA |
Manual-flow metadata_json is not a JSON object |
403 |
DEPOSIT_NOT_ALLOWED |
Deposits are disabled for this customer |
403 |
PAYMENT_METHOD_NOT_AVAILABLE |
Provider/method is not eligible for this account/customer |
403 |
PERMISSION_DENIED |
Account does not belong to the customer |
404 |
CUSTOMER_NOT_FOUND |
Customer record was not found |
409 |
RET_ERR_DUPLICATE |
Duplicate idempotency_key for the same customer; the prior transaction is not replayed |
5xx |
RET_ERR_NOSERVICE |
Payment provider is not loaded or unavailable |
5xx |
RET_TECH_PROBLEM |
Durable transaction or finance-operation state could not be written; inspect any returned transaction and query by idempotency key before retrying |
An automatic provider-call error can be returned after the transaction has
already been created; such error responses include transaction. If an error
arrives after status 11 (processing_ledger) was durably stored, never retry
the request with a new key. Query transaction history using the same
idempotency_key; duplicate keys are rejected rather than replaying the
original response.