Bag Transaction Fees
Submit app-provided transaction fees at the bag level.
Overview
A channel submits a transaction fee for a single bag. Violet validates the submission (bag exists, bag is owned by your app, amounts and currency are valid, configuration permits app-provided fees), persists the fee, and returns the outcome. The fee value you send is treated as authoritative; Violet does not recompute it.
Preview. The submission, validation, and persistence path is live. The fee does not yet affect distributions — that consumption behavior ships in a later release.
Request body
transaction_fee_total_amount
integer
Yes
The total fee, in minor units (e.g. cents). Authoritative — Violet uses this value as-is. Must be ≥ 0.
transaction_fee_percentage_amount
integer
Yes
The portion of the fee attributable to your percentage component, in minor units. Submit 0 if it does not apply. Must be ≥ 0.
transaction_fee_fixed_amount
integer
Yes
The portion of the fee attributable to your fixed component, in minor units. Submit 0 if it does not apply. Must be ≥ 0.
currency
string
Yes
ISO 4217 currency code. Must match the bag's base currency. Compared case-insensitively.
source_type
string
Yes
Must be APP_PROVIDED. Any other value is rejected.
source_provider
string
No
Optional free-form identifier for the source of the fee.
source_reference_id
string
No
Optional. Your own reference ID for this fee, for reconciliation.
idempotency_key
string
No (recommended)
Safe-retry key. See Idempotency below.
The submitting app is identified by the X-Violet-App-Id header and must own the bag. A submission for a bag owned by a different app is rejected with HTTP 403.
Example request
curl -X PUT "https://api.violet.io/v1/bags/1234567/transaction_fee" \
-H "X-Violet-Token: <token>" \
-H "X-Violet-App-Secret: <app-secret>" \
-H "X-Violet-App-Id: 10355" \
-H "Content-Type: application/json" \
-d '{
"transaction_fee_total_amount": 390,
"transaction_fee_percentage_amount": 290,
"transaction_fee_fixed_amount": 100,
"currency": "USD",
"source_type": "APP_PROVIDED",
"source_provider": "acme",
"source_reference_id": "acme-fee-8842",
"idempotency_key": "bag-1234567-fee-v1"
}'Successful response (HTTP 200)
The outcome field indicates the result of the submission:
outcome
Meaning
accepted
The fee was validated and stored.
duplicate_accepted
An identical submission under the same idempotency_key was already accepted; no new record was created.
config_conflict_rejected
Your app is not currently permitted to supply app-provided fees for this bag's merchant. Returned as HTTP 200 with error_code = CONFIG_DISALLOWS_APP_PROVIDED_FEE and a stored rejection record.
A configuration conflict is returned as a 200 with outcome = config_conflict_rejected, not as a 4xx. Validation failures (below) are 4xx and use the standard error envelope.
Error responses (HTTP 4xx)
Validation failures use Violet's standard error envelope:
error
HTTP
code
When
bag_not_found
404
4201
The bag_id does not resolve to a bag.
insufficient_permissions
403
9901
The bag is not owned by the submitting app.
missing_parameter
400
9002
A required field is missing (an amount, currency, or source_type).
invalid_currency
400
4226
currency does not match the bag's base currency.
invalid_amount
400
4465
An amount is negative.
invalid_source_type
400
4466
source_type is not APP_PROVIDED.
duplicate_conflict
409
4467
The idempotency_key was reused with different values.
Idempotency
idempotency_key is optional but recommended for safe retries.
Resubmitting the same values under the same key returns
duplicate_acceptedand does not create a second record.Reusing the same key with different values returns
duplicate_conflict(HTTP 409).Without a key, each submission is processed independently (no de-duplication).
Validation order
Violet validates in this order and returns the first failure:
Bag exists (
bag_not_found).Bag owned by the submitting app (
insufficient_permissions).All three amounts present (
missing_parameter).Amounts non-negative (
invalid_amount).currencypresent and matches the bag's base currency (missing_parameter/invalid_currency).source_typepresent and equal toAPP_PROVIDED(missing_parameter/invalid_source_type).Idempotency check (
duplicate_accepted/duplicate_conflict).Configuration gate (
config_conflict_rejectedif not permitted).Accept and persist (
accepted).
Available endpoints:
Last updated
Was this helpful?