diff --git a/CRM/Stripe/PaymentIntent.php b/CRM/Stripe/PaymentIntent.php
index 641a1842e51dcc970c3560a4405921b187d5905e..54c87f1cc8a255044f245822035f3c9fb0f6cd07 100644
--- a/CRM/Stripe/PaymentIntent.php
+++ b/CRM/Stripe/PaymentIntent.php
@@ -341,7 +341,6 @@ class CRM_Stripe_PaymentIntent {
    *
    * @return object
    * @throws \CRM_Core_Exception
-   * @throws \CiviCRM_API3_Exception
    * @throws \Stripe\Exception\ApiErrorException
    */
   public function processIntent(array $params) {
diff --git a/Civi/Api4/Action/StripePaymentintent/ProcessPublic.php b/Civi/Api4/Action/StripePaymentintent/ProcessPublic.php
index dec6afc83a8b1038ea4f7c1af5343187d1647c50..dee3b13c4ee8462325ca04f605395ab51da93d24 100644
--- a/Civi/Api4/Action/StripePaymentintent/ProcessPublic.php
+++ b/Civi/Api4/Action/StripePaymentintent/ProcessPublic.php
@@ -12,6 +12,10 @@
 
 namespace Civi\Api4\Action\StripePaymentintent;
 
+use Brick\Math\RoundingMode;
+use Brick\Money\Context\DefaultContext;
+use Brick\Money\Money;
+
 /**
  * Process a Stripe Intent with public/anonymous permissions
  *
@@ -81,37 +85,40 @@ class ProcessPublic extends \Civi\Api4\Generic\AbstractAction {
    */
   protected $csrfToken = '';
 
-  /**
-   * @param \Civi\Api4\Generic\Result $result
-   *
-   * @return array
-   * @throws \CRM_Core_Exception
-   * @throws \CiviCRM_API3_Exception
-   */
   /**
    * @param \Civi\Api4\Generic\Result $result
    *
    * @return void
-   * @throws \API_Exception
    * @throws \CRM_Core_Exception
-   * @throws \CiviCRM_API3_Exception
    * @throws \Stripe\Exception\ApiErrorException
    */
   public function _run(\Civi\Api4\Generic\Result $result) {
     if (class_exists('\Civi\Firewall\Firewall')) {
       $firewall = new \Civi\Firewall\Firewall();
       if (!$firewall->checkIsCSRFTokenValid(\CRM_Utils_Type::validate($this->csrfToken, 'String'))) {
-        throw new \API_Exception($firewall->getReasonDescription());
+        throw new \CRM_Core_Exception($firewall->getReasonDescription());
       }
     }
 
     if (empty($this->amount) && !$this->setup) {
       \Civi::log('stripe')->error(__CLASS__ . 'missing amount and not capture or setup');
-      throw new \API_Exception('Bad request');
+      throw new \CRM_Core_Exception('Bad request');
     }
+
+    // If we configured a minimum allowed amount for processing check it here
+    $minAmount = \Civi::settings()->get('stripe_minamount');
+    if (!empty($minAmount)) {
+      $moneyAmount = Money::of($this->amount, $this->currency, new DefaultContext(), RoundingMode::CEILING);
+      $moneyMinAmount = Money::of($minAmount, $this->currency, new DefaultContext(), RoundingMode::CEILING);
+      if ($moneyAmount->isLessThan($moneyMinAmount)) {
+        \Civi::log('stripe')->error(__CLASS__ . 'amount: ' . $this->amount . ' is less than min_amount: ' . $minAmount);
+        throw new \CRM_Core_Exception('Bad request');
+      }
+    }
+
     if (empty($this->paymentProcessorID)) {
       \Civi::log('stripe')->error(__CLASS__ . ' missing paymentProcessorID');
-      throw new \API_Exception('Bad request');
+      throw new \CRM_Core_Exception('Bad request');
     }
 
     $intentProcessor = new \CRM_Stripe_PaymentIntent();
@@ -135,7 +142,7 @@ class ProcessPublic extends \Civi\Api4\Generic\AbstractAction {
       $result->exchangeArray($processIntentResult->data);
     }
     else {
-      throw new \API_Exception($processIntentResult->message);
+      throw new \CRM_Core_Exception($processIntentResult->message);
     }
   }
 
diff --git a/settings/stripe.setting.php b/settings/stripe.setting.php
index a677cfa7f65f999d49e43f564fa67cf4ddccf1a2..ca3a97f3a725d2021cd0f8abb24a0391e334472b 100644
--- a/settings/stripe.setting.php
+++ b/settings/stripe.setting.php
@@ -222,4 +222,23 @@ Do NOT enable unless you\'ve enabled this feature on your Stripe account - see <
       ]
     ],
   ],
+  'stripe_minamount' => [
+    'name' => 'stripe_minamount',
+    'type' => 'Integer',
+    'html_type' => 'text',
+    'default' => 0,
+    'is_domain' => 1,
+    'is_contact' => 0,
+    'title' => E::ts('Minimum amount that Stripe is allowed to process.'),
+    'description' => E::ts('Default 0. This can help reduce the impact of card testing attacks as they tend to use low amounts eg. $1. If you know that your will never take payments under eg. $10 you can set that here and the request will fail for anything below that amount.'),
+    'html_attributes' => [
+      'size' => 10,
+      'maxlength' => 3,
+    ],
+    'settings_pages' => [
+      'stripe' => [
+        'weight' => 120,
+      ]
+    ],
+  ],
 ];