diff --git a/service/config/sample.yml b/service/config/sample.yml
index 6e64bf459d21e1b8df18880c0ccc2fc5933233d6..ee51a9f8adc46a98d782cb2fb1352d0e561dfe4f 100644
--- a/service/config/sample.yml
+++ b/service/config/sample.yml
@@ -55,10 +55,12 @@ stripe:
   idempotencyKeyGenerator: secret://stripe.idempotencyKeyGenerator
   boostDescription: >
     Example
-  supportedCurrencies:
-    - xts
-  # - ...
-  # - Nth supported currency
+  supportedCurrenciesByPaymentMethod:
+    CARD:
+      - usd
+      - eur
+    SEPA_DEBIT:
+      - eur
 
 
 braintree:
@@ -70,10 +72,9 @@ braintree:
   merchantAccounts:
     # ISO 4217 currency code and its corresponding sub-merchant account
     'xts': unset
-  supportedCurrencies:
-    - xts
-  # - ...
-  # - Nth supported currency
+  supportedCurrenciesByPaymentMethod:
+    PAYPAL:
+      - usd
 
 dynamoDbClientConfiguration:
   region: us-west-2 # AWS Region
@@ -367,6 +368,7 @@ subscription: # configuration for Stripe subscriptions
             BRAINTREE: plan_example # braintree Plan ID
 
 oneTimeDonations:
+  sepaMaxTransactionSizeEuros: '10000'
   boost:
     level: 1
     expiration: P90D
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java
index df57213526628fea0bd943d9d5bdb10564be8150..e764735b22153a010d7f8076b4c4d3fbdff9f517 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/WhisperServerService.java
@@ -455,12 +455,11 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
         config.getAdminEventLoggingConfiguration().logName());
 
     StripeManager stripeManager = new StripeManager(config.getStripe().apiKey().value(), subscriptionProcessorExecutor,
-        config.getStripe().idempotencyKeyGenerator().value(), config.getStripe().boostDescription(), config.getStripe()
-        .supportedCurrencies());
+        config.getStripe().idempotencyKeyGenerator().value(), config.getStripe().boostDescription(), config.getStripe().supportedCurrenciesByPaymentMethod());
     BraintreeManager braintreeManager = new BraintreeManager(config.getBraintree().merchantId(),
         config.getBraintree().publicKey(), config.getBraintree().privateKey().value(),
         config.getBraintree().environment(),
-        config.getBraintree().supportedCurrencies(), config.getBraintree().merchantAccounts(),
+        config.getBraintree().supportedCurrenciesByPaymentMethod(), config.getBraintree().merchantAccounts(),
         config.getBraintree().graphqlUrl(), config.getBraintree().circuitBreaker(), subscriptionProcessorExecutor,
         subscriptionProcessorRetryExecutor);
 
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/BraintreeConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/BraintreeConfiguration.java
index 1e8aa85b2de65e70b63a783dec480602dc35175e..32291b3e385787bc2ff18527765199f9ca550b03 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/BraintreeConfiguration.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/BraintreeConfiguration.java
@@ -12,6 +12,7 @@ import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
+import org.whispersystems.textsecuregcm.subscriptions.PaymentMethod;
 
 /**
  * @param merchantId          the Braintree merchant ID
@@ -27,7 +28,7 @@ public record BraintreeConfiguration(@NotBlank String merchantId,
                                      @NotBlank String publicKey,
                                      @NotNull SecretString privateKey,
                                      @NotBlank String environment,
-                                     @NotEmpty Set<@NotBlank String> supportedCurrencies,
+                                     @Valid @NotEmpty Map<PaymentMethod, Set<@NotBlank String>> supportedCurrenciesByPaymentMethod,
                                      @NotBlank String graphqlUrl,
                                      @NotEmpty Map<String, String> merchantAccounts,
                                      @NotNull
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/OneTimeDonationConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/OneTimeDonationConfiguration.java
index c3516fb36bd6a9e51b38a7132ce327133edfc429..a128b0270f2580999fb2313e8fcdfb96d133c548 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/OneTimeDonationConfiguration.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/OneTimeDonationConfiguration.java
@@ -5,6 +5,7 @@
 
 package org.whispersystems.textsecuregcm.configuration;
 
+import java.math.BigDecimal;
 import java.time.Duration;
 import java.util.Map;
 import javax.validation.Valid;
@@ -18,7 +19,8 @@ import javax.validation.constraints.Positive;
  */
 public record OneTimeDonationConfiguration(@Valid ExpiringLevelConfiguration boost,
                                            @Valid ExpiringLevelConfiguration gift,
-                                           Map<String, @Valid OneTimeDonationCurrencyConfiguration> currencies) {
+                                           Map<String, @Valid OneTimeDonationCurrencyConfiguration> currencies,
+                                           BigDecimal sepaMaxTransactionSizeEuros) {
 
   /**
    * @param badge      the numeric donation level ID
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/StripeConfiguration.java b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/StripeConfiguration.java
index 4682b0cde332982e4cdb697930f4cd48d93bd67e..cef38975710b68e56e8e3e102c4a6b6b046ff172 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/configuration/StripeConfiguration.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/configuration/StripeConfiguration.java
@@ -5,15 +5,18 @@
 
 package org.whispersystems.textsecuregcm.configuration;
 
+import java.util.Map;
 import java.util.Set;
+import javax.validation.Valid;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 import org.whispersystems.textsecuregcm.configuration.secrets.SecretBytes;
 import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
+import org.whispersystems.textsecuregcm.subscriptions.PaymentMethod;
 
 public record StripeConfiguration(@NotNull SecretString apiKey,
                                   @NotNull SecretBytes idempotencyKeyGenerator,
                                   @NotBlank String boostDescription,
-                                  @NotEmpty Set<@NotBlank String> supportedCurrencies) {
+                                  @Valid @NotEmpty Map<PaymentMethod, Set<@NotBlank String>> supportedCurrenciesByPaymentMethod) {
 }
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java
index 7e6966c09ad2aef8e4e88a802d02a78749d892b7..5087f29161384cea150575ad94e5f4b178e761ed 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java
@@ -118,6 +118,7 @@ public class SubscriptionController {
   private static final String RECEIPT_ISSUED_COUNTER_NAME = MetricsUtil.name(SubscriptionController.class, "receiptIssued");
   private static final String PROCESSOR_TAG_NAME = "processor";
   private static final String TYPE_TAG_NAME = "type";
+  private static final String EURO_CURRENCY_CODE = "EUR";
 
   public SubscriptionController(
       @Nonnull Clock clock,
@@ -170,8 +171,8 @@ public class SubscriptionController {
 
           final List<String> supportedPaymentMethods = Arrays.stream(PaymentMethod.values())
               .filter(paymentMethod -> subscriptionProcessorManagers.stream()
-                  .anyMatch(manager -> manager.getSupportedCurrencies().contains(currency)
-                      && manager.supportsPaymentMethod(paymentMethod)))
+                  .anyMatch(manager -> manager.supportsPaymentMethod(paymentMethod)
+                      && manager.getSupportedCurrenciesForPaymentMethod(paymentMethod).contains(currency)))
               .map(PaymentMethod::name)
               .collect(Collectors.toList());
 
@@ -377,7 +378,7 @@ public class SubscriptionController {
 
   private SubscriptionProcessorManager getManagerForPaymentMethod(PaymentMethod paymentMethod) {
     return switch (paymentMethod) {
-      case CARD -> stripeManager;
+      case CARD, SEPA_DEBIT -> stripeManager;
       case PAYPAL -> braintreeManager;
     };
   }
@@ -604,6 +605,7 @@ public class SubscriptionController {
     @Min(1)
     public long amount;
     public Long level;
+    public PaymentMethod paymentMethod = PaymentMethod.CARD;
   }
 
   public static class CreatePayPalBoostRequest extends CreateBoostRequest {
@@ -651,15 +653,14 @@ public class SubscriptionController {
   }
 
   /**
-   * Validates that the currency and amount in the request are supported by the {@code manager} and exceed the minimum
-   * permitted amount
+   * Validates that the currency is supported by the {@code manager} and {@code request.paymentMethod}
+   * and that the amount meets minimum and maximum constraints.
    *
    * @throws BadRequestException indicates validation failed. Inspect {@code response.error} for details
    */
   private void validateRequestCurrencyAmount(CreateBoostRequest request, BigDecimal amount,
       SubscriptionProcessorManager manager) {
-
-    if (!manager.supportsCurrency(request.currency.toLowerCase(Locale.ROOT))) {
+    if (!manager.getSupportedCurrenciesForPaymentMethod(request.paymentMethod).contains(request.currency.toLowerCase(Locale.ROOT))) {
       throw new BadRequestException(Response.status(Status.BAD_REQUEST)
           .entity(Map.of("error", "unsupported_currency")).build());
     }
@@ -675,6 +676,16 @@ public class SubscriptionController {
               "error", "amount_below_currency_minimum",
               "minimum", minCurrencyAmountMajorUnits.toString())).build());
     }
+
+    if (request.paymentMethod == PaymentMethod.SEPA_DEBIT &&
+        amount.compareTo(SubscriptionCurrencyUtil.convertConfiguredAmountToApiAmount(
+            EURO_CURRENCY_CODE,
+            oneTimeDonationConfiguration.sepaMaxTransactionSizeEuros())) > 0) {
+      throw new BadRequestException(Response.status(Status.BAD_REQUEST)
+          .entity(Map.of(
+              "error", "amount_above_sepa_limit",
+              "maximum", oneTimeDonationConfiguration.sepaMaxTransactionSizeEuros().toString())).build());
+    }
   }
 
   @POST
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/BraintreeManager.java b/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/BraintreeManager.java
index db1eeac80d36c2415ef914c3b712af3d91f95fa1..1d30c487e1e83676125e49ce6b2c4c82d66f577e 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/BraintreeManager.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/BraintreeManager.java
@@ -55,13 +55,13 @@ public class BraintreeManager implements SubscriptionProcessorManager {
   private final BraintreeGateway braintreeGateway;
   private final BraintreeGraphqlClient braintreeGraphqlClient;
   private final Executor executor;
-  private final Set<String> supportedCurrencies;
+  private final Map<PaymentMethod, Set<String>> supportedCurrenciesByPaymentMethod;
   private final Map<String, String> currenciesToMerchantAccounts;
 
   public BraintreeManager(final String braintreeMerchantId, final String braintreePublicKey,
       final String braintreePrivateKey,
       final String braintreeEnvironment,
-      final Set<String> supportedCurrencies,
+      final Map<PaymentMethod, Set<String>> supportedCurrenciesByPaymentMethod,
       final Map<String, String> currenciesToMerchantAccounts,
       final String graphqlUri,
       final CircuitBreakerConfiguration circuitBreakerConfiguration,
@@ -70,7 +70,7 @@ public class BraintreeManager implements SubscriptionProcessorManager {
 
     this(new BraintreeGateway(braintreeEnvironment, braintreeMerchantId, braintreePublicKey,
             braintreePrivateKey),
-        supportedCurrencies,
+        supportedCurrenciesByPaymentMethod,
         currenciesToMerchantAccounts,
         new BraintreeGraphqlClient(FaultTolerantHttpClient.newBuilder()
             .withName("braintree-graphql")
@@ -86,19 +86,20 @@ public class BraintreeManager implements SubscriptionProcessorManager {
   }
 
   @VisibleForTesting
-  BraintreeManager(final BraintreeGateway braintreeGateway, final Set<String> supportedCurrencies,
+  BraintreeManager(final BraintreeGateway braintreeGateway,
+      final Map<PaymentMethod, Set<String>> supportedCurrenciesByPaymentMethod,
       final Map<String, String> currenciesToMerchantAccounts, final BraintreeGraphqlClient braintreeGraphqlClient,
       final Executor executor) {
     this.braintreeGateway = braintreeGateway;
-    this.supportedCurrencies = supportedCurrencies;
+    this.supportedCurrenciesByPaymentMethod = supportedCurrenciesByPaymentMethod;
     this.currenciesToMerchantAccounts = currenciesToMerchantAccounts;
     this.braintreeGraphqlClient = braintreeGraphqlClient;
     this.executor = executor;
   }
 
   @Override
-  public Set<String> getSupportedCurrencies() {
-    return supportedCurrencies;
+  public Set<String> getSupportedCurrenciesForPaymentMethod(final PaymentMethod paymentMethod) {
+    return supportedCurrenciesByPaymentMethod.getOrDefault(paymentMethod, Collections.emptySet());
   }
 
   @Override
@@ -111,11 +112,6 @@ public class BraintreeManager implements SubscriptionProcessorManager {
     return paymentMethod == PaymentMethod.PAYPAL;
   }
 
-  @Override
-  public boolean supportsCurrency(final String currency) {
-    return supportedCurrencies.contains(currency.toLowerCase(Locale.ROOT));
-  }
-
   @Override
   public CompletableFuture<PaymentDetails> getPaymentDetails(final String paymentId) {
     return CompletableFuture.supplyAsync(() -> {
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/PaymentMethod.java b/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/PaymentMethod.java
index e472a8bfe66315300869e41010241f112486f52c..4738437eae673b6d5e820d44b4c4adb559afa431 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/PaymentMethod.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/PaymentMethod.java
@@ -14,4 +14,8 @@ public enum PaymentMethod {
    * A PayPal account
    */
   PAYPAL,
+  /**
+   * A SEPA debit account
+   */
+  SEPA_DEBIT,
 }
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/StripeManager.java b/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/StripeManager.java
index 57b4fb93305fc8db1afdede3e41ec7b46ed04918..c1dc9c6b175bb087acdfa1d78bc7e4a360d3d20d 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/StripeManager.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/StripeManager.java
@@ -77,14 +77,14 @@ public class StripeManager implements SubscriptionProcessorManager {
   private final Executor executor;
   private final byte[] idempotencyKeyGenerator;
   private final String boostDescription;
-  private final Set<String> supportedCurrencies;
+  private final Map<PaymentMethod, Set<String>> supportedCurrenciesByPaymentMethod;
 
   public StripeManager(
       @Nonnull String apiKey,
       @Nonnull Executor executor,
       @Nonnull byte[] idempotencyKeyGenerator,
       @Nonnull String boostDescription,
-      @Nonnull Set<String> supportedCurrencies) {
+      @Nonnull Map<PaymentMethod, Set<String>> supportedCurrenciesByPaymentMethod) {
     if (Strings.isNullOrEmpty(apiKey)) {
       throw new IllegalArgumentException("apiKey cannot be empty");
     }
@@ -95,7 +95,7 @@ public class StripeManager implements SubscriptionProcessorManager {
       throw new IllegalArgumentException("idempotencyKeyGenerator cannot be empty");
     }
     this.boostDescription = Objects.requireNonNull(boostDescription);
-    this.supportedCurrencies = supportedCurrencies;
+    this.supportedCurrenciesByPaymentMethod = supportedCurrenciesByPaymentMethod;
   }
 
   @Override
@@ -105,12 +105,7 @@ public class StripeManager implements SubscriptionProcessorManager {
 
   @Override
   public boolean supportsPaymentMethod(PaymentMethod paymentMethod) {
-    return paymentMethod == PaymentMethod.CARD;
-  }
-
-  @Override
-  public boolean supportsCurrency(final String currency) {
-    return supportedCurrencies.contains(currency);
+    return paymentMethod == PaymentMethod.CARD || paymentMethod == PaymentMethod.SEPA_DEBIT;
   }
 
   private RequestOptions commonOptions() {
@@ -184,8 +179,8 @@ public class StripeManager implements SubscriptionProcessorManager {
   }
 
   @Override
-  public Set<String> getSupportedCurrencies() {
-    return supportedCurrencies;
+  public Set<String> getSupportedCurrenciesForPaymentMethod(final PaymentMethod paymentMethod) {
+    return supportedCurrenciesByPaymentMethod.getOrDefault(paymentMethod, Collections.emptySet());
   }
 
   /**
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/SubscriptionProcessorManager.java b/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/SubscriptionProcessorManager.java
index 02bc5d3d719dd82152f05ec7e0887a7be5804a59..7be7b2c2d3b87e4ea2700955e46e2b8170e211e4 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/SubscriptionProcessorManager.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/SubscriptionProcessorManager.java
@@ -19,9 +19,7 @@ public interface SubscriptionProcessorManager {
 
   boolean supportsPaymentMethod(PaymentMethod paymentMethod);
 
-  boolean supportsCurrency(String currency);
-
-  Set<String> getSupportedCurrencies();
+  Set<String> getSupportedCurrenciesForPaymentMethod(PaymentMethod paymentMethod);
 
   CompletableFuture<PaymentDetails> getPaymentDetails(String paymentId);
 
diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SubscriptionControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SubscriptionControllerTest.java
index c7a1710410a876c800321e49af2896f8c54165bf..a3a99a3bae460b13f36fffb2234eb228b01e1a71 100644
--- a/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SubscriptionControllerTest.java
+++ b/service/src/test/java/org/whispersystems/textsecuregcm/controllers/SubscriptionControllerTest.java
@@ -68,6 +68,7 @@ import org.whispersystems.textsecuregcm.storage.IssuedReceiptsManager;
 import org.whispersystems.textsecuregcm.storage.SubscriptionManager;
 import org.whispersystems.textsecuregcm.subscriptions.BraintreeManager;
 import org.whispersystems.textsecuregcm.subscriptions.ChargeFailure;
+import org.whispersystems.textsecuregcm.subscriptions.PaymentMethod;
 import org.whispersystems.textsecuregcm.subscriptions.ProcessorCustomer;
 import org.whispersystems.textsecuregcm.subscriptions.StripeManager;
 import org.whispersystems.textsecuregcm.subscriptions.SubscriptionProcessor;
@@ -98,9 +99,11 @@ class SubscriptionControllerTest {
           when(manager.supportsPaymentMethod(any()))
               .thenCallRealMethod();
         });
-    when(STRIPE_MANAGER.getSupportedCurrencies())
-        .thenReturn(Set.of("usd", "jpy", "bif"));
-    when(BRAINTREE_MANAGER.getSupportedCurrencies())
+    when(STRIPE_MANAGER.getSupportedCurrenciesForPaymentMethod(PaymentMethod.CARD))
+        .thenReturn(Set.of("usd", "jpy", "bif", "eur"));
+    when(STRIPE_MANAGER.getSupportedCurrenciesForPaymentMethod(PaymentMethod.SEPA_DEBIT))
+        .thenReturn(Set.of("eur"));
+    when(BRAINTREE_MANAGER.getSupportedCurrenciesForPaymentMethod(PaymentMethod.PAYPAL))
         .thenReturn(Set.of("usd", "jpy"));
   }
 
@@ -134,7 +137,8 @@ class SubscriptionControllerTest {
 
   @Test
   void testCreateBoostPaymentIntentAmountBelowCurrencyMinimum() {
-    when(STRIPE_MANAGER.supportsCurrency("usd")).thenReturn(true);
+    when(STRIPE_MANAGER.getSupportedCurrenciesForPaymentMethod(PaymentMethod.CARD))
+        .thenReturn(Set.of("usd", "jpy", "bif", "eur"));
     final Response response = RESOURCE_EXTENSION.target("/v1/subscription/boost/create")
         .request()
         .post(Entity.json("""
@@ -146,16 +150,58 @@ class SubscriptionControllerTest {
             """));
     assertThat(response.getStatus()).isEqualTo(400);
     assertThat(response.hasEntity()).isTrue();
-    assertThat(response.readEntity(Map.class))
-        .isNotNull()
-        .containsAllEntriesOf(Map.of(
-            "error", "amount_below_currency_minimum",
-            "minimum", "2.50"
-        ));
+    final Map responseMap = response.readEntity(Map.class);
+    assertThat(responseMap.get("error")).isEqualTo("amount_below_currency_minimum");
+    assertThat(responseMap.get("minimum")).isEqualTo("2.50");
+  }
+
+  @Test
+  void testCreateBoostPaymentIntentAmountAboveSepaLimit() {
+    when(STRIPE_MANAGER.getSupportedCurrenciesForPaymentMethod(PaymentMethod.SEPA_DEBIT))
+        .thenReturn(Set.of("eur"));
+    final Response response = RESOURCE_EXTENSION.target("/v1/subscription/boost/create")
+        .request()
+        .post(Entity.json("""
+              {
+                "currency": "EUR",
+                "amount": 1000001,
+                "level": null,
+                "paymentMethod": "SEPA_DEBIT"
+              }
+            """));
+    assertThat(response.getStatus()).isEqualTo(400);
+    assertThat(response.hasEntity()).isTrue();
+
+    final Map responseMap = response.readEntity(Map.class);
+    assertThat(responseMap.get("error")).isEqualTo("amount_above_sepa_limit");
+    assertThat(responseMap.get("maximum")).isEqualTo("10000");
+  }
+
+  @Test
+  void testCreateBoostPaymentIntentUnsupportedCurrency() {
+    when(STRIPE_MANAGER.getSupportedCurrenciesForPaymentMethod(PaymentMethod.SEPA_DEBIT))
+        .thenReturn(Set.of("eur"));
+    final Response response = RESOURCE_EXTENSION.target("/v1/subscription/boost/create")
+        .request()
+        .post(Entity.json("""
+              {
+                "currency": "USD",
+                "amount": 3000,
+                "level": null,
+                "paymentMethod": "SEPA_DEBIT"
+              }
+            """));
+    assertThat(response.getStatus()).isEqualTo(400);
+    assertThat(response.hasEntity()).isTrue();
+
+    final Map responseMap = response.readEntity(Map.class);
+    assertThat(responseMap.get("error")).isEqualTo("unsupported_currency");
   }
 
   @Test
   void testCreateBoostPaymentIntentLevelAmountMismatch() {
+    when(STRIPE_MANAGER.getSupportedCurrenciesForPaymentMethod(PaymentMethod.CARD))
+        .thenReturn(Set.of("usd", "jpy", "bif", "eur"));
     final Response response = RESOURCE_EXTENSION.target("/v1/subscription/boost/create")
         .request()
         .post(Entity.json("""
@@ -171,9 +217,10 @@ class SubscriptionControllerTest {
 
   @Test
   void testCreateBoostPaymentIntent() {
+    when(STRIPE_MANAGER.getSupportedCurrenciesForPaymentMethod(PaymentMethod.CARD))
+        .thenReturn(Set.of("usd", "jpy", "bif", "eur"));
     when(STRIPE_MANAGER.createPaymentIntent(anyString(), anyLong(), anyLong()))
         .thenReturn(CompletableFuture.completedFuture(PAYMENT_INTENT));
-    when(STRIPE_MANAGER.supportsCurrency("usd")).thenReturn(true);
 
     String clientSecret = "some_client_secret";
     when(PAYMENT_INTENT.getClientSecret()).thenReturn(clientSecret);
@@ -643,7 +690,6 @@ class SubscriptionControllerTest {
 
   @Test
   void getSubscriptionConfiguration() {
-
     when(BADGE_TRANSLATOR.translate(any(), eq("B1"))).thenReturn(new Badge("B1", "cat1", "name1", "desc1",
         List.of("l", "m", "h", "x", "xx", "xxx"), "SVG",
         List.of(new BadgeSvg("sl", "sd"), new BadgeSvg("ml", "md"), new BadgeSvg("ll", "ld"))));
@@ -667,7 +713,7 @@ class SubscriptionControllerTest {
         .request()
         .get(GetSubscriptionConfigurationResponse.class);
 
-    assertThat(response.currencies()).containsKeys("usd", "jpy", "bif").satisfies(currencyMap -> {
+    assertThat(response.currencies()).containsKeys("usd", "jpy", "bif", "eur").satisfies(currencyMap -> {
       assertThat(currencyMap).extractingByKey("usd").satisfies(currency -> {
         assertThat(currency.minimum()).isEqualByComparingTo(
             BigDecimal.valueOf(2.5).setScale(2, RoundingMode.HALF_EVEN));
@@ -709,6 +755,19 @@ class SubscriptionControllerTest {
             Map.of("5", BigDecimal.valueOf(5000), "15", BigDecimal.valueOf(15000), "35", BigDecimal.valueOf(35000)));
         assertThat(currency.supportedPaymentMethods()).isEqualTo(List.of("CARD"));
       });
+
+      assertThat(currencyMap).extractingByKey("eur").satisfies(currency -> {
+        assertThat(currency.minimum()).isEqualByComparingTo(
+            BigDecimal.valueOf(3));
+        assertThat(currency.oneTime()).isEqualTo(
+            Map.of("1",
+                List.of(BigDecimal.valueOf(5), BigDecimal.valueOf(10),
+                    BigDecimal.valueOf(20), BigDecimal.valueOf(30), BigDecimal.valueOf(50), BigDecimal.valueOf(100)), "100",
+                List.of(BigDecimal.valueOf(5))));
+        assertThat(currency.subscription()).isEqualTo(
+            Map.of("5", BigDecimal.valueOf(5), "15", BigDecimal.valueOf(15),"35", BigDecimal.valueOf(35)));
+        assertThat(currency.supportedPaymentMethods()).isEqualTo(List.of("CARD", "SEPA_DEBIT"));
+      });
     });
 
     assertThat(response.levels()).containsKeys("1", "5", "15", "35", "100").satisfies(levelsMap -> {
@@ -821,6 +880,11 @@ class SubscriptionControllerTest {
                 processorIds:
                   STRIPE: S1
                   BRAINTREE: O1
+              eur:
+                amount: '5'
+                processorIds:
+                  STRIPE: A1
+                  BRAINTREE: B1
           15:
             badge: B2
             prices:
@@ -839,6 +903,11 @@ class SubscriptionControllerTest {
                 processorIds:
                   STRIPE: S2
                   BRAINTREE: O2
+              eur:
+                amount: '15'
+                processorIds:
+                  STRIPE: A2
+                  BRAINTREE: B2
           35:
             badge: B3
             prices:
@@ -857,6 +926,11 @@ class SubscriptionControllerTest {
                 processorIds:
                   STRIPE: S3
                   BRAINTREE: O3
+              eur:
+                amount: '35'
+                processorIds:
+                  STRIPE: A3
+                  BRAINTREE: B3
         """;
 
     private static final String ONETIME_CONFIG_YAML = """
@@ -879,6 +953,16 @@ class SubscriptionControllerTest {
               - '8'
               - '9'
               - '10'
+          eur:
+            minimum: '3'
+            gift: '5'
+            boosts:
+              - '5'
+              - '10'
+              - '20'
+              - '30'
+              - '50'
+              - '100'
           jpy:
             minimum: '250'
             gift: '2000'
@@ -899,6 +983,7 @@ class SubscriptionControllerTest {
               - '8000'
               - '9000'
               - '10000'
+        sepaMaxTransactionSizeEuros: '10000'
         """;
 
   }
diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/subscriptions/BraintreeManagerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/subscriptions/BraintreeManagerTest.java
index 924dcee83058fbec3558f862b525fc4890e36365..fff9204ffe7aa62c73b0c5a27be69b2b11aba796 100644
--- a/service/src/test/java/org/whispersystems/textsecuregcm/subscriptions/BraintreeManagerTest.java
+++ b/service/src/test/java/org/whispersystems/textsecuregcm/subscriptions/BraintreeManagerTest.java
@@ -29,7 +29,7 @@ class BraintreeManagerTest {
   void setup() {
     braintreeGateway = mock(BraintreeGateway.class);
     braintreeManager = new BraintreeManager(braintreeGateway,
-        Set.of("usd"),
+        Map.of(PaymentMethod.CARD, Set.of("usd")),
         Map.of("usd", "usdMerchant"),
         mock(BraintreeGraphqlClient.class),
         Executors.newSingleThreadExecutor());