Skip to main content
Bank Transfer plugin configuration is organized across three levels. Most business-related settings can be updated at runtime without requiring a service restart. It’s important to distinguish between tenant identity and Midaz organization scope, as they serve different purposes. The tenant is resolved from the authenticated request context through the tenantId JWT claim. It is responsible for infrastructure-level isolation, including multi-tenancy platform database resolution and access to tenant-scoped secrets. The X-Organization-Id header defines the Midaz organization scope within that tenant. It is required on all organization-scoped transfer routes, regardless of the deployment mode. Requests that omit this header or provide a value that is not a valid UUID return a 400 response. Background processes, such as the TED IN poller and reconciliation workers, do not receive request headers. In single-tenant deployments, these processes use the ORGANIZATION_ID environment variable as the organization context.

Configuration levels


Bank Transfer plugin configuration is divided into three levels:
  • Infrastructure configuration (managed by DevOps) controls URLs, credentials, authentication settings, and timeouts. Changes require a service restart.
  • Tenant settings (managed through the Admin API by the Product team) control transfer limits, fee policies, and operating-hours overrides. Changes take effect without restarting the service.
  • Account settings (managed through the Admin API by the Product team) control limits and restrictions for individual accounts. Changes take effect without restarting the service.

Business decisions you can configure


These are the settings GPMs and product teams care about. All of them are managed via the Admin API at runtime — no deploy required.

Transfer limits

Set daily and monthly volume caps at two levels:
  • Per organization — applies to transfers for one Midaz organization inside the resolved tenant
  • Per account — applies to a specific end-user account (overrides organization defaults)
Limits cover both total amount and number of transactions. Set these to manage risk and comply with BACEN requirements.

Fee policy

Control whether the plugin charges a fee on TED OUT, TED IN, and P2P transfers. Fee rules are defined in the Fees Engine and applied per organization. See Fees Engine for configuration details.

Fail-open vs. fail-closed

If the fee calculation service is unavailable at the moment of a transfer, you have two options:
  • Fail-open — allow the transfer to proceed without charging a fee
  • Fail-closed — block the transfer until the fee service is available again
The default fee-service policy is fail-open (FEES_FAIL_CLOSED_DEFAULT=false). Change this per organization via the Admin API when you need fee-service outages to block transfers. TED IN has its own safety switch, BTF_FEES_TED_IN_FAIL_OPEN, which defaults to true so inbound funds are credited with fee=0 if plugin-fees is unavailable.

TED IN receiving

Incoming transfers are disabled by default. Enable TED IN per organization once your JD SPB credentials are configured and the polling worker is active.

Operating hours overrides

The plugin enforces BACEN’s TED operating window by default. You can configure custom windows per tenant policy — for example, restricting transfers to business hours only — within BACEN limits.

Infrastructure configuration


Deploy-time environment variables (URLs, credentials, TLS, persistence, integrations, security keys) are set by DevOps and require a service restart. See the full reference in Environment variables.

Runtime configuration (Admin API)


Tenant-level and account-level settings are managed via the Admin API — no restart required. Changes take effect immediately (subject to cache TTL for tenant settings). Configurable settings include:
  • Transfer limits (daily and monthly, per organization and per account)
  • Fee behavior (fail-open or fail-closed when the fee service is unavailable)
  • TED IN receiving (enabled or disabled per organization)
  • Operating hours overrides (custom windows within BACEN limits)
See the Admin API reference for the full list of configurable fields and request format.

Systemplane-managed settings

The settings below are managed at runtime through the systemplane (Admin API), not at deploy time. Each one has a corresponding environment variable name that still exists in the codebase, but the config loader ignores these env vars and emits a deprecation WARN if they are set — assigning them via the environment has no effect. Use the systemplane to change them.
AreaSettings
Rate limitingRATE_LIMIT_ENABLED, RATE_LIMIT_MAX, RATE_LIMIT_EXPIRY_SEC
CORSCORS_ALLOWED_ORIGINS, CORS_ALLOWED_METHODS, CORS_ALLOWED_HEADERS (default origin is wildcard * when unconfigured; not validated at startup)
Fee policyFEES_FAIL_CLOSED_DEFAULT, FEES_MAX_FEE_AMOUNT_CENTS, FEES_REFUND_ON_DEVOLUCAO, BTF_FEES_TED_IN_FAIL_OPEN
Usage limitsUSAGE_LIMITS_ENABLED, USAGE_LIMIT_DAILY_CENTS, USAGE_LIMIT_MONTHLY_CENTS
Operating hoursTRANSFER_OPERATING_OPEN, TRANSFER_OPERATING_CLOSE, TRANSFER_OPERATING_TIMEZONE
Idempotency / duplicate guardIDEMPOTENCY_REQUIRE_REDIS, DUPLICATE_GUARD_TTL_SEC
RoutingROUTING_* (all routing-rule settings)
JD timeout & retry tuningJD_TIMEOUT_MS, JD_MAX_RETRIES, JD_VALIDATE_EXTERNAL_SIGNATURE
JD polling tuningJD_POLL_MAX_MESSAGES_PER_CYCLE, JD_POLL_RECOVERY_BATCH_SIZE, JD_POLL_DISABLE_OPERATING_HOURS_WINDOW
Reconciliation tuningBTF_RECONCILIATION_BATCH_SIZE, BTF_RECONCILIATION_MAX_ATTEMPTS, BTF_RECONCILIATION_STALE_AFTER_SEC, BTF_RECONCILIATION_TICK_DEADLINE_SECONDS, RECONCILIATION_PENDING_ALERT_THRESHOLD
RabbitMQ publish tuningRABBITMQ_MAX_RETRIES, RABBITMQ_PUBLISH_TIMEOUT_MS, RABBITMQ_RETRY_BACKOFF_MS, RABBITMQ_ROUTING_KEY_PREFIX
Webhook delivery tuningWEBHOOK_TIMEOUT_MS, WEBHOOK_MAX_RETRIES, WEBHOOK_RETRY_BACKOFF_MS, WEBHOOK_ALLOW_UNSIGNED_BROKER_EVENTS, WEBHOOK_UNSIGNED_BROKER_EVENTS_GRACE_SEC
Setting any of the names above via the environment has no effect and is WARN-logged as deprecated. They exist only as deprecated env twins of runtime/systemplane-managed settings.
When CORS is unconfigured, the default allowed origin is the wildcard * — any origin can call the API — and it is not validated at startup. For production, set explicit origins through the systemplane key cors.allowed_origins instead of leaving the wildcard.