diff --git a/src/main/java/im/quicksy/server/configuration/Configuration.java b/src/main/java/im/quicksy/server/configuration/Configuration.java
index f3a6e3dc5c49d396a67399bde2468a3bc25cc92b..857f4db648650ea0e43fe5254d2ebc004e1ee147 100644
--- a/src/main/java/im/quicksy/server/configuration/Configuration.java
+++ b/src/main/java/im/quicksy/server/configuration/Configuration.java
@@ -31,8 +31,7 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.time.Duration;
-import java.util.HashMap;
-import java.util.Optional;
+import java.util.*;
 
 public class Configuration {
 
@@ -43,12 +42,9 @@ public class Configuration {
     private Web web = new Web();
     private HashMap<String, DatabaseConfiguration> db;
     private PayPal payPal = new PayPal();
-    private String twilioAuthToken;
 
-    private String nexmoApiKey;
-    private String nexmoPhoneNumber;
+    private TreeMap<String, ProviderConfiguration> provider;
 
-    private String nexmoApiSecret;
     private String cimAuthToken;
     private Version minVersion;
     private Duration accountInactivity = Duration.ofDays(28);
@@ -135,22 +131,6 @@ public class Configuration {
         return new DatabaseConfigurationBundle.Builder().setEjabberdConfiguration(db.get("ejabberd")).setQuicksyConfiguration(db.get("quicksy")).build();
     }
 
-    public String getTwilioAuthToken() {
-        return twilioAuthToken;
-    }
-
-    public String getNexmoApiKey() {
-        return nexmoApiKey;
-    }
-
-    public String getNexmoApiSecret() {
-        return nexmoApiSecret;
-    }
-
-    public String getNexmoPhoneNumber() {
-        return nexmoPhoneNumber;
-    }
-
     public Optional<String> getCimAuthToken() {
         return Optional.ofNullable(cimAuthToken);
     }
@@ -171,6 +151,10 @@ public class Configuration {
         return minVersion;
     }
 
+    public TreeMap<String, Configuration.ProviderConfiguration> getProvider() {
+        return this.provider;
+    }
+
     public static class XMPP {
         private String host = "localhost";
         private int port = 5347;
@@ -232,4 +216,18 @@ public class Configuration {
             return username != null && password != null && signature != null;
         }
     }
+
+
+    public static class ProviderConfiguration {
+        private Map<String, String> parameter;
+        private List<Integer> deny;
+
+        public Map<String, String> getParameter() {
+            return parameter;
+        }
+
+        public List<Integer> getDeny() {
+            return deny;
+        }
+    }
 }
diff --git a/src/main/java/im/quicksy/server/controller/BaseController.java b/src/main/java/im/quicksy/server/controller/BaseController.java
index d037d27dfdc0e70b273fcd31fe1b287e308eb4f6..1e2719bc607906426c83a1a748d6872afa6a2417 100644
--- a/src/main/java/im/quicksy/server/controller/BaseController.java
+++ b/src/main/java/im/quicksy/server/controller/BaseController.java
@@ -21,6 +21,7 @@ import com.github.zafarkhaja.semver.Version;
 import com.google.common.base.Splitter;
 import com.google.common.net.InetAddresses;
 import im.quicksy.server.configuration.Configuration;
+import im.quicksy.server.verification.MetaVerificationProvider;
 import im.quicksy.server.verification.NexmoVerificationProvider;
 import im.quicksy.server.verification.TwilioVerificationProvider;
 import im.quicksy.server.verification.VerificationProvider;
@@ -52,7 +53,7 @@ public class BaseController {
     protected static Pattern PIN_PATTERN = Pattern.compile("^[0-9]{6}$");
     protected static Pattern UUID_PATTERN = Pattern.compile("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
 
-    protected static final VerificationProvider VERIFICATION_PROVIDER = new NexmoVerificationProvider();
+    protected static final VerificationProvider VERIFICATION_PROVIDER = new MetaVerificationProvider();
 
     protected static InetAddress getClientIp(Request request) {
         final InetAddress remote = InetAddresses.forString(request.ip());
diff --git a/src/main/java/im/quicksy/server/verification/AbstractVerificationProvider.java b/src/main/java/im/quicksy/server/verification/AbstractVerificationProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f82e9fec2a419db9954fc61b3989c0e730e04d3
--- /dev/null
+++ b/src/main/java/im/quicksy/server/verification/AbstractVerificationProvider.java
@@ -0,0 +1,11 @@
+package im.quicksy.server.verification;
+
+import java.util.Map;
+
+public abstract class AbstractVerificationProvider implements VerificationProvider {
+
+    public AbstractVerificationProvider(final Map<String, String> parameter) {
+
+    }
+
+}
diff --git a/src/main/java/im/quicksy/server/verification/MetaVerificationProvider.java b/src/main/java/im/quicksy/server/verification/MetaVerificationProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..1068f6cc6ec3bcb2974ca6411aca926811caaaa9
--- /dev/null
+++ b/src/main/java/im/quicksy/server/verification/MetaVerificationProvider.java
@@ -0,0 +1,92 @@
+package im.quicksy.server.verification;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.i18n.phonenumbers.Phonenumber;
+import im.quicksy.server.configuration.Configuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+public class MetaVerificationProvider implements VerificationProvider {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(MetaVerificationProvider.class);
+
+    final List<ProviderWrapper> providerList;
+
+    public MetaVerificationProvider() {
+        final TreeMap<String, Configuration.ProviderConfiguration> provider = Configuration.getInstance().getProvider();
+        ImmutableList.Builder<ProviderWrapper> providerListBuilder = ImmutableList.builder();
+        for(final Map.Entry<String,Configuration.ProviderConfiguration> entry : provider.entrySet()) {
+            final String className = entry.getKey();
+            final Configuration.ProviderConfiguration configuration = entry.getValue();
+            final Class<? extends AbstractVerificationProvider> clazz;
+            try {
+                clazz = (Class<? extends AbstractVerificationProvider>) Class.forName(className);
+            } catch (ClassNotFoundException | ClassCastException e) {
+                LOGGER.warn("No VerificationProvider found matching for name {}", className);
+                continue;
+            }
+            final AbstractVerificationProvider providerInstance;
+            try {
+                Constructor<? extends AbstractVerificationProvider> constructor = clazz.getConstructor(Map.class);
+                providerInstance = constructor.newInstance(configuration.getParameter());
+            } catch (NoSuchMethodException e) {
+                LOGGER.warn("{} does not implement Map<String,String> constructor", clazz.getName());
+                continue;
+            } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
+                LOGGER.warn("Unable to construct VerificationProvider",e);
+                continue;
+            }
+            providerListBuilder.add(new ProviderWrapper(configuration.getDeny(), providerInstance));
+            LOGGER.info("found provider {} ", className);
+        }
+        final ImmutableList<ProviderWrapper> providerList = providerListBuilder.build();
+        LOGGER.info("Found {} providers", providerList.size());
+        if (providerList.size() == 0) {
+            throw new IllegalStateException("No VerificationProviders found");
+        }
+        this.providerList = providerList;
+    }
+
+    @Override
+    public boolean verify(Phonenumber.PhoneNumber phoneNumber, String pin) throws RequestFailedException {
+        return getVerificationProvider(phoneNumber).verify(phoneNumber, pin);
+    }
+
+    @Override
+    public void request(Phonenumber.PhoneNumber phoneNumber, Method method) throws RequestFailedException {
+        getVerificationProvider(phoneNumber).request(phoneNumber, method);
+    }
+
+    @Override
+    public void request(Phonenumber.PhoneNumber phoneNumber, Method method, String language) throws RequestFailedException {
+        getVerificationProvider(phoneNumber).request(phoneNumber, method, language);
+    }
+
+    private AbstractVerificationProvider getVerificationProvider(Phonenumber.PhoneNumber phoneNumber) throws RequestFailedException {
+        final int countryCode = phoneNumber.getCountryCode();
+        for(ProviderWrapper providerWrapper : this.providerList) {
+            if (providerWrapper.deny.contains(countryCode)) {
+                continue;
+            }
+            return providerWrapper.provider;
+        }
+        throw new RequestFailedException(String.format("No Verification Provider found to handle country code %d", countryCode));
+    }
+
+    private static class ProviderWrapper {
+        private final List<Integer> deny;
+        private final AbstractVerificationProvider provider;
+
+        private ProviderWrapper(List<Integer> deny, AbstractVerificationProvider provider) {
+            this.deny = deny;
+            this.provider = provider;
+        }
+    }
+}
diff --git a/src/main/java/im/quicksy/server/verification/MockVerificationProvider.java b/src/main/java/im/quicksy/server/verification/MockVerificationProvider.java
index 6465d689e0cd856d3ffc1b16e4f8c11dfbac6855..c6c3e91af9ef5d891868159f06aabcdd29f4b8b1 100644
--- a/src/main/java/im/quicksy/server/verification/MockVerificationProvider.java
+++ b/src/main/java/im/quicksy/server/verification/MockVerificationProvider.java
@@ -20,10 +20,16 @@ import com.google.i18n.phonenumbers.Phonenumber;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class MockVerificationProvider implements VerificationProvider {
+import java.util.Map;
+
+public class MockVerificationProvider extends AbstractVerificationProvider {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(MockVerificationProvider.class);
 
+    public MockVerificationProvider(Map<String, String> parameter) {
+        super(parameter);
+    }
+
     @Override
     public boolean verify(Phonenumber.PhoneNumber phoneNumber, String pin) {
         return pin != null && pin.length() == 6 && String.valueOf(phoneNumber.getNationalNumber()).startsWith(pin);
diff --git a/src/main/java/im/quicksy/server/verification/NexmoVerificationProvider.java b/src/main/java/im/quicksy/server/verification/NexmoVerificationProvider.java
index 4a997587a5a3fd9fb8a3cc3bd2ad7b24ef47d036..a4bcba9b1c5fbe2abd9007ead72916ddd5d2f00c 100644
--- a/src/main/java/im/quicksy/server/verification/NexmoVerificationProvider.java
+++ b/src/main/java/im/quicksy/server/verification/NexmoVerificationProvider.java
@@ -1,5 +1,6 @@
 package im.quicksy.server.verification;
 
+import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
@@ -18,8 +19,9 @@ import java.security.SecureRandom;
 import java.time.Duration;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
-public class NexmoVerificationProvider implements VerificationProvider {
+public class NexmoVerificationProvider extends AbstractVerificationProvider {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(NexmoVerificationProvider.class);
 
@@ -44,6 +46,17 @@ public class NexmoVerificationProvider implements VerificationProvider {
             .expireAfterWrite(Duration.ofMinutes(5))
             .build();
 
+    private final String phoneNumber;
+    private final String apiKey;
+    private final String apiSecret;
+
+    public NexmoVerificationProvider(Map<String, String> parameter) {
+        super(parameter);
+        this.phoneNumber = parameter.get("phone_number");
+        this.apiKey = Preconditions.checkNotNull(parameter.get("api_key"));
+        this.apiSecret = Preconditions.checkNotNull(parameter.get("api_secret"));
+    }
+
     @Override
     public boolean verify(Phonenumber.PhoneNumber phoneNumber, String input) throws RequestFailedException {
         final Pin pin = PIN_CACHE.getIfPresent(phoneNumber);
@@ -70,7 +83,7 @@ public class NexmoVerificationProvider implements VerificationProvider {
         final Pin pin = Pin.generate();
         PIN_CACHE.put(phoneNumber, pin);
         final String to = String.format("%d%d", phoneNumber.getCountryCode(), phoneNumber.getNationalNumber());
-        final String nexmoPhoneNumber = Configuration.getInstance().getNexmoPhoneNumber();
+        final String nexmoPhoneNumber = this.phoneNumber;
         final String from;
         if (Strings.isNullOrEmpty(nexmoPhoneNumber) || COUNTRY_CODES_SUPPORTING_ALPHA_NUMERIC.contains(phoneNumber.getCountryCode())) {
             from = BRAND_NAME;
@@ -83,8 +96,8 @@ public class NexmoVerificationProvider implements VerificationProvider {
                         .add("from", from)
                         .add("text", String.format(MESSAGE, pin.toString()))
                         .add("to", to)
-                        .add("api_key", Configuration.getInstance().getNexmoApiKey())
-                        .add("api_secret", Configuration.getInstance().getNexmoApiSecret())
+                        .add("api_key", this.apiKey)
+                        .add("api_secret", this.apiSecret)
                         .build())
                 .url(NEXMO_API_URL)
                 .build());
diff --git a/src/main/java/im/quicksy/server/verification/TwilioVerificationProvider.java b/src/main/java/im/quicksy/server/verification/TwilioVerificationProvider.java
index d8ad2f91244aad3fc0f71be066756ed089c1bbdf..f366e0dc2f5e0fe02fa7635cda0625c0af68edce 100644
--- a/src/main/java/im/quicksy/server/verification/TwilioVerificationProvider.java
+++ b/src/main/java/im/quicksy/server/verification/TwilioVerificationProvider.java
@@ -16,6 +16,7 @@
 
 package im.quicksy.server.verification;
 
+import com.google.common.base.Preconditions;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonSyntaxException;
@@ -34,12 +35,10 @@ import java.io.UnsupportedEncodingException;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLEncoder;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
-public class TwilioVerificationProvider implements VerificationProvider {
+public class TwilioVerificationProvider extends AbstractVerificationProvider {
 
 
     public static final int PHONE_VERIFICATION_INCORRECT = 60022;
@@ -51,6 +50,23 @@ public class TwilioVerificationProvider implements VerificationProvider {
     private static final Logger LOGGER = LoggerFactory.getLogger(TwilioVerificationProvider.class);
     private final GsonBuilder gsonBuilder = new GsonBuilder();
 
+    private final String authToken;
+
+    public TwilioVerificationProvider(Map<String, String> parameter) {
+        super(parameter);
+        this.authToken = Preconditions.checkNotNull(parameter.get("auth_token"));
+    }
+
+    public TwilioVerificationProvider() {
+        super(Collections.emptyMap());
+        final TreeMap<String, Configuration.ProviderConfiguration> provider = Configuration.getInstance().getProvider();
+        final Configuration.ProviderConfiguration myConfiguration = provider.get(getClass().getName());
+        if (myConfiguration == null) {
+            throw new RuntimeException("No configuration found for "+getClass().getSimpleName());
+        }
+        this.authToken = Preconditions.checkNotNull(myConfiguration.getParameter().get("auth_token"));
+    }
+
     @Override
     public boolean verify(Phonenumber.PhoneNumber phoneNumber, String pin) throws RequestFailedException {
         Map<String, String> params = new HashMap<>();
@@ -124,7 +140,7 @@ public class TwilioVerificationProvider implements VerificationProvider {
         try {
             final Gson gson = this.gsonBuilder.create();
             final HttpURLConnection connection = (HttpURLConnection) new URL(TWILIO_API_URL + method).openConnection();
-            connection.setRequestProperty("X-Authy-API-Key", Configuration.getInstance().getTwilioAuthToken());
+            connection.setRequestProperty("X-Authy-API-Key", this.authToken);
             if (params != null && params.size() > 0) {
                 connection.setRequestMethod("POST");
                 final String output = getQuery(params);