Skip to main content

Brands, currencies & 3D Secure

Edge Pay is multi-brand and multi-currency by design. A single tenant can present several commercial brands, acquire in several currencies, and apply different 3D Secure policies per currency — all from the same payment.yaml. This page explains how the three mechanisms fit together.

Brand routing

The brand_routing block decides which brand a payment session belongs to:

brand_routing:
default_brand: default
resolve_from:
- source: url_param
param: brand
- source: session_field
field: brand_code

Resolution walks the resolve_from chain in order:

  1. url_param — if the payment URL carries ?brand=<code>, that brand is used.
  2. session_field — otherwise, the brand_code bound to the payment session (set when the link was issued from a document or by an agent) is used.
  3. If neither resolves, default_brand applies.

default_brand should be set to your primary commercial brand at implementation time.

The brands map

Brands live in the brands map. The baseline ships a single empty default:

brands:
default: {} # Empty brand = root-level config; add per-brand entries at fork time

An empty brand inherits the root configuration — the root-level branding and copy blocks apply unchanged. This is the correct shape for a single-brand tenant: one brand, no duplication.

Multi-brand tenants add named entries during implementation, each carrying only the overrides that differ from root — typically branding (logo, colors) and copy (brand voice, sign-offs):

brands:
default: {}
meridian-uk:
branding:
name: Meridian Travel UK
logo:
url: "https://assets.example.com/meridian-uk/logo.svg"
copy:
success_message: Thank you for booking with Meridian Travel UK.
meridian-us:
branding:
name: Meridian Travel US

A common implementation pattern is a dedicated brand for the trade channel — an "agent portal" brand set as the default when agents, rather than guests, are the primary payers. This pattern is proven in production.

Brand is identity, not presentation

A core platform rule: in document and session data, a brand is identity only — a {code, name} pair. Hex colors, fonts, and logo URLs never travel in data. Instead, the brand code is the key into the brands map (and the equivalent map in your document configuration), and all presentation resolves from tenant config at render time.

This matters for two reasons:

  • Consistency — a rebrand is a config change in one place, not a data migration.
  • Integrity — payment pages cannot be styled by whoever constructs a URL; only codes that exist in your brands map resolve, and unknown codes fall back to the default brand.

The same meta.brand object that drives document rendering in Edge Docs drives payment-page branding, so a guest moving from a proposal to its payment link stays inside one visual identity. See Schemas for how meta.brand is structured in document data.

Per-currency merchant accounts

Braintree settles each currency into a dedicated merchant account. The merchant_accounts map names one account per acquiring currency:

gateways:
braintree:
merchant_accounts:
DEFAULT: "vault::braintree_merchant_id"
USD: meridian_travel_usd
CAD: meridian_travel_cad
GBP: meridian_travel_gbp
AUD: meridian_travel_aud
EUR: meridian_travel_eur
NZD: meridian_travel_nzd
  • Values are Braintree merchant account names, not secrets — they appear in plain text.
  • DEFAULT is the fallback when a transaction's currency has no explicit entry.
  • At payment time, the platform selects the account matching the booking's currency; the guest is charged in that currency with no conversion surprise.
Declare all acquiring currencies at onboarding

List every currency you will acquire in when the tenant is first set up, even ones you will not use immediately. Adding a currency later means provisioning a new Braintree merchant account, updating configuration, and re-verifying the payment flow for that currency — retrofitting is consistently more painful than declaring up front.

Per-currency 3D Secure

3D Secure (3DS) policy is also set per acquiring currency:

three_d_secure:
per_currency:
DEFAULT: false
GBP: true # SCA regulation — keep true for UK/EU acquiring
EUR: true # SCA regulation — keep true for UK/EU acquiring

The baseline reflects the regulatory reality: GBP and EUR are true because Strong Customer Authentication (SCA) applies to UK and EU acquiring — do not disable 3DS for these currencies. Other currencies default to false, where 3DS is optional and often traded off against checkout friction; enable it per currency if your fraud posture warrants it.

The same per_currency structure appears both at gateway level and on the braintree_card payment method, so the policy travels with the method configuration.

How a payment resolves brand and currency

When a payment link is opened, the platform combines the mechanisms above:

  1. The payment session carries the booking's meta.currency (an ISO 4217 code) and meta.brand ({code, name}) — the same metadata that drove the source document.
  2. Currency selects the merchant account from merchant_accounts (falling back to DEFAULT) and the 3DS policy from three_d_secure.per_currency.
  3. Brand is resolved through brand_routing (URL parameter, then session field, then default) and selects the branding and copy overrides from the brands map.

The result: a guest paying a GBP booking under your UK brand sees the UK logo and copy, is charged through the GBP merchant account, and is challenged with 3DS — while a USD booking under another brand of the same tenant takes a different path through the same configuration, with no per-brand or per-currency code anywhere.