For the complete documentation index, see llms.txt. This page is also available as Markdown.

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.

Request body

Field
Type
Required
Description

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.

All three amount fields are required and must be present, even when a component is 0. Amounts are integer minor units; do not send decimals. Violet does not recalculate the percentage/fixed components against the bag total — send your resolved values.

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.

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_accepted and 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:

  1. Bag exists (bag_not_found).

  2. Bag owned by the submitting app (insufficient_permissions).

  3. All three amounts present (missing_parameter).

  4. Amounts non-negative (invalid_amount).

  5. currency present and matches the bag's base currency (missing_parameter / invalid_currency).

  6. source_type present and equal to APP_PROVIDED (missing_parameter / invalid_source_type).

  7. Idempotency check (duplicate_accepted / duplicate_conflict).

  8. Configuration gate (config_conflict_rejected if not permitted).

  9. Accept and persist (accepted).

Available endpoints:

Last updated

Was this helpful?