diff --git a/README.md b/README.md
index 48e674f6..50205979 100644
--- a/README.md
+++ b/README.md
@@ -53,16 +53,28 @@ Setting the `endpoint` can be done with any of the following (searched in order)
 
 Setting the `credentials` can be done with any of the following (searched in order):
 
+- `jenkins.rest.api.token`
+- `jenkinsRestApiToken`
+- `JENKINS_REST_API_TOKEN`
 - `jenkins.rest.credentials`
 - `jenkinsRestCredentials`
 - `JENKINS_REST_CREDENTIALS`
 
 ## Credentials
 
-jenkins-rest credentials can take 1 of 2 forms:
+jenkins-rest credentials can take 1 of 3 forms:
 
-- Colon delimited username and password: __admin:password__ 
-- Base64 encoded username and password: __YWRtaW46cGFzc3dvcmQ=__ 
+- Colon delimited username and api token: __admin:apiToken__
+  - use `JenkinsClient.builder().apiToken("admin:apiToken")`
+- Colon delimited username and password: __admin:password__
+  - use `JenkinsClient.builder().credentials("admin:password")`
+- Base64 encoded username followed by password __YWRtaW46cGFzc3dvcmQ=__ or api token __YWRtaW46YXBpVG9rZW4=__
+  - use `JenkinsClient.builder().apiToken("YWRtaW46YXBpVG9rZW4=")`
+  - use `JenkinsClient.builder().credentials("YWRtaW46cGFzc3dvcmQ=")`
+
+The Jenkins crumb is automatically requested for the anonymous and the username:password authentication methods.
+It is not requested when you use the apiToken as it is not needed.
+For more details, see the [Cloudbees crumb documentation](https://support.cloudbees.com/hc/en-us/articles/219257077-CSRF-Protection-Explained).
 
 ## Examples
 
@@ -80,12 +92,17 @@ Running mock tests can be done like so:
 
 	./gradlew clean build mockTest
 	
-Running integration tests can be done like so (requires existing jenkins instance):
+Running integration tests require an existing jenkins instance which can be obtained with docker:
 
+        docker build -t jenkins-rest/jenkins src/main/docker
+        docker run -d --rm -p 8080:8080 --name jenkins-rest jenkins-rest/jenkins
 	./gradlew clean build integTest 
 
 ### Integration tests settings
 
+If you use the provided docker instance, there is no other preparation necessary.
+If you wish to run integration tests against your own Jenkins server, the requirements are outlined in the next section.
+
 #### Jenkins instance requirements
 
 - a running instance accessible on http://127.0.0.1:8080 (can be changed in the gradle.properties file)
@@ -95,6 +112,7 @@ Running integration tests can be done like so (requires existing jenkins instanc
 - Plugins
   - [CloudBees Credentials](https://plugins.jenkins.io/cloudbees-credentials): otherwise an http 500 error occurs when accessing
 to http://127.0.0.1:8080/job/test-folder/job/test-folder-1/ `java.lang.NoClassDefFoundError: com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProvider`
+  - [CloudBees Folder](https://plugins.jenkins.io/cloudbees-folder) plugin installed
   - [OWASP Markup Formatter](https://plugins.jenkins.io/antisamy-markup-formatter) configured to use `Safe HTML`
   - [Configuration As Code](https://plugins.jenkins.io/configuration-as-code) plugin installed
 
@@ -103,7 +121,7 @@ This project provides instructions to setup a [pre-configured Docker container](
 #### Integration tests configuration
 
 - jenkins url and authentication method used by the tests are defined in the `gradle.properties` file
-- by default, tests use the `credentials` authentication but this can be changed to use the `token` authentication
+- by default, tests use the `apiToken` authentication but this can be changed to use the other authentication methods.
 
 
 #### Running integration tests from within your IDE
diff --git a/build.gradle b/build.gradle
index cbf0e14e..99ff372c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -60,6 +60,8 @@ tasks.withType(JavaCompile) {
 }
 
 task mockTest(type: Test) {
+    group = "Verification"
+    description = "Mock tests"
     useTestNG()
     include '**/**MockTest*'
     maxParallelForks = 2
@@ -70,6 +72,8 @@ task mockTest(type: Test) {
 }
 
 task integTest(type: Test, dependsOn: mockTest) {
+    group = "Verification"
+    description = "Integration tests - Jenkins must be running. See the README."
     doFirst {
         def integProjectDir = project.file("${buildDir}/integ-projects")
         if (!integProjectDir.exists()) {
@@ -86,13 +90,13 @@ task integTest(type: Test, dependsOn: mockTest) {
         events 'started', 'passed', 'failed'
     }
     def authentication = [:]
-    def possibleAuth = project.findProperty('testJenkinsRestCredentials')
+    def possibleAuth = project.findProperty('testJenkinsRestApiToken')
     if (possibleAuth) {
-        authentication['test.jenkins.rest.credentials'] = possibleAuth
+        authentication['test.jenkins.rest.api.token'] = possibleAuth
     } else {
-        possibleAuth = project.findProperty('testJenkinsRestToken')
+        possibleAuth = project.findProperty('testJenkinsRestCredentials')
         if (possibleAuth) {
-            authentication['test.jenkins.rest.token'] = possibleAuth
+            authentication['test.jenkins.rest.credentials'] = possibleAuth
         } else {
             logger.quiet 'No authentication parameters found. Assuming anonymous...'
         }
diff --git a/src/main/java/com/cdancy/jenkins/rest/JenkinsAuthentication.java b/src/main/java/com/cdancy/jenkins/rest/JenkinsAuthentication.java
index 75b97505..65d3eee8 100644
--- a/src/main/java/com/cdancy/jenkins/rest/JenkinsAuthentication.java
+++ b/src/main/java/com/cdancy/jenkins/rest/JenkinsAuthentication.java
@@ -36,10 +36,11 @@ public class JenkinsAuthentication extends Credentials {
      * Create instance of JenkinsAuthentication
      * 
      * @param authValue value to use for authentication type HTTP header.
-     * @param authType authentication type (e.g. Basic, Bearer, Anonymous).
+     * @param authType authentication type (e.g. UsernamePassword, ApiToken, Anonymous).
      */
     private JenkinsAuthentication(final String authValue, final AuthenticationType authType) {
-        super(null, authType == AuthenticationType.Basic && authValue.contains(":")
+        //super(authValue != null ? (authValue.contains(":") ? authValue.split(":")[0] : null) : null, (authType == AuthenticationType.UsernamePassword || authType == AuthenticationType.ApiToken) && authValue.contains(":")
+        super(null, (authType == AuthenticationType.UsernamePassword || authType == AuthenticationType.ApiToken) && authValue.contains(":")
                 ? base64().encode(authValue.getBytes())
                 : authValue);
         this.authType = authType;    
@@ -64,26 +65,26 @@ public static class Builder {
         private AuthenticationType authType;
 
         /**
-         * Set 'Basic' credentials.
+         * Set 'UsernamePassword' credentials.
          * 
-         * @param basicCredentials value to use for 'Basic' credentials.
+         * @param usernamePassword value to use for 'UsernamePassword' credentials.
          * @return this Builder.
          */
-        public Builder credentials(final String basicCredentials) {
-            this.authValue = Objects.requireNonNull(basicCredentials);
-            this.authType = AuthenticationType.Basic;
+        public Builder credentials(final String usernamePassword) {
+            this.authValue = Objects.requireNonNull(usernamePassword);
+            this.authType = AuthenticationType.UsernamePassword;
             return this;
         }
 
         /**
-         * Set 'Bearer' credentials.
-         * 
-         * @param tokenCredentials value to use for 'Bearer' credentials.
+         * Set 'ApiToken' credentials.
+         *
+         * @param apiTokenCredentials value to use for 'ApiToken' credentials.
          * @return this Builder.
          */
-        public Builder token(final String tokenCredentials) {
-            this.authValue = Objects.requireNonNull(tokenCredentials);
-            this.authType = AuthenticationType.Bearer;
+        public Builder apiToken(final String apiTokenCredentials) {
+            this.authValue = Objects.requireNonNull(apiTokenCredentials);
+            this.authType = AuthenticationType.ApiToken;
             return this;
         }
 
diff --git a/src/main/java/com/cdancy/jenkins/rest/JenkinsClient.java b/src/main/java/com/cdancy/jenkins/rest/JenkinsClient.java
index cd344344..bae330e1 100644
--- a/src/main/java/com/cdancy/jenkins/rest/JenkinsClient.java
+++ b/src/main/java/com/cdancy/jenkins/rest/JenkinsClient.java
@@ -168,14 +168,15 @@ public Builder credentials(final String optionallyBase64EncodedCredentials) {
         }
 
         /**
-         * Optional token to use for authentication.
+         * Optional Api token to use for authentication.
+         * This is not a Bearer token, hence the name apiToken.
          *
-         * @param token authentication token.
+         * @param apiToken authentication token.
          * @return this Builder.
          */
-        public Builder token(final String token) {
+        public Builder apiToken(final String apiToken) {
             authBuilder = JenkinsAuthentication.builder()
-                    .token(token);
+                    .apiToken(apiToken);
             return this;
         }
 
diff --git a/src/main/java/com/cdancy/jenkins/rest/JenkinsConstants.java b/src/main/java/com/cdancy/jenkins/rest/JenkinsConstants.java
index a5259744..1ce07aa4 100644
--- a/src/main/java/com/cdancy/jenkins/rest/JenkinsConstants.java
+++ b/src/main/java/com/cdancy/jenkins/rest/JenkinsConstants.java
@@ -28,8 +28,8 @@ public class JenkinsConstants {
     public static final String CREDENTIALS_SYSTEM_PROPERTY = "jenkins.rest.credentials";
     public static final String CREDENTIALS_ENVIRONMENT_VARIABLE = CREDENTIALS_SYSTEM_PROPERTY.replaceAll("\\.", "_").toUpperCase();
 
-    public static final String TOKEN_SYSTEM_PROPERTY = "jenkins.rest.token";
-    public static final String TOKEN_ENVIRONMENT_VARIABLE = TOKEN_SYSTEM_PROPERTY.replaceAll("\\.", "_").toUpperCase();
+    public static final String API_TOKEN_SYSTEM_PROPERTY = "jenkins.rest.api.token";
+    public static final String API_TOKEN_ENVIRONMENT_VARIABLE = API_TOKEN_SYSTEM_PROPERTY.replaceAll("\\.", "_").toUpperCase();
 
     public static final String DEFAULT_ENDPOINT = "http://127.0.0.1:7990";
 
diff --git a/src/main/java/com/cdancy/jenkins/rest/JenkinsUtils.java b/src/main/java/com/cdancy/jenkins/rest/JenkinsUtils.java
index c3e9c8c8..bbbe9b36 100644
--- a/src/main/java/com/cdancy/jenkins/rest/JenkinsUtils.java
+++ b/src/main/java/com/cdancy/jenkins/rest/JenkinsUtils.java
@@ -26,8 +26,8 @@
 import static com.cdancy.jenkins.rest.JenkinsConstants.ENDPOINT_SYSTEM_PROPERTY;
 import static com.cdancy.jenkins.rest.JenkinsConstants.JCLOUDS_PROPERTY_ID;
 import static com.cdancy.jenkins.rest.JenkinsConstants.JCLOUDS_VARIABLE_ID;
-import static com.cdancy.jenkins.rest.JenkinsConstants.TOKEN_ENVIRONMENT_VARIABLE;
-import static com.cdancy.jenkins.rest.JenkinsConstants.TOKEN_SYSTEM_PROPERTY;
+import static com.cdancy.jenkins.rest.JenkinsConstants.API_TOKEN_ENVIRONMENT_VARIABLE;
+import static com.cdancy.jenkins.rest.JenkinsConstants.API_TOKEN_SYSTEM_PROPERTY;
 
 import com.google.common.base.Throwables;
 
@@ -159,28 +159,29 @@ public static String inferEndpoint() {
     }
 
     /**
-     * Find credentials (Basic, Bearer, or Anonymous) from system/environment.
+     * Find credentials (ApiToken, UsernamePassword, or Anonymous) from system/environment.
      *
      * @return BitbucketCredentials
      */
     public static JenkinsAuthentication inferAuthentication() {
 
-        // 1.) Check for "Basic" auth credentials.
         final JenkinsAuthentication.Builder inferAuth = JenkinsAuthentication.builder();
+        // 1.) Check for API Token as this requires no crumb hence is faster
         String authValue = JenkinsUtils
+                .retriveExternalValue(API_TOKEN_SYSTEM_PROPERTY,
+                        API_TOKEN_ENVIRONMENT_VARIABLE);
+        if (authValue != null) {
+            inferAuth.apiToken(authValue);
+            return inferAuth.build();
+        }
+
+        // 2.) Check for UsernamePassword auth credentials.
+        authValue = JenkinsUtils
                 .retriveExternalValue(CREDENTIALS_SYSTEM_PROPERTY,
                         CREDENTIALS_ENVIRONMENT_VARIABLE);
         if (authValue != null) {
             inferAuth.credentials(authValue);
-        } else {
-
-            // 2.) Check for "Bearer" auth token.
-            authValue = JenkinsUtils
-                    .retriveExternalValue(TOKEN_SYSTEM_PROPERTY,
-                            TOKEN_ENVIRONMENT_VARIABLE);
-            if (authValue != null) {
-                inferAuth.token(authValue);
-            }
+            return inferAuth.build();
         }
 
         // 3.) If neither #1 or #2 find anything "Anonymous" access is assumed.
diff --git a/src/main/java/com/cdancy/jenkins/rest/auth/AuthenticationType.java b/src/main/java/com/cdancy/jenkins/rest/auth/AuthenticationType.java
index 8cc9d4bd..7cab43f3 100644
--- a/src/main/java/com/cdancy/jenkins/rest/auth/AuthenticationType.java
+++ b/src/main/java/com/cdancy/jenkins/rest/auth/AuthenticationType.java
@@ -22,18 +22,24 @@
  */
 public enum AuthenticationType {
 
-    Basic("Basic"),
-    Bearer("Bearer"),
-    Anonymous("");
+    UsernamePassword("UsernamePassword", "Basic"),
+    ApiToken("ApiToken", "Basic"),
+    Anonymous("Anonymous", "");
 
-    private final String type;
+    private final String authName;
+    private final String authScheme;
 
-    private AuthenticationType(final String type) {
-        this.type = type;
+    private AuthenticationType(final String authName, final String authScheme) {
+        this.authName = authName;
+        this.authScheme = authScheme;
+    }
+
+    public String getAuthScheme() {
+        return authScheme;
     }
 
     @Override
     public String toString() {
-        return type;
+        return authName;
     }
 }
diff --git a/src/main/java/com/cdancy/jenkins/rest/domain/user/ApiToken.java b/src/main/java/com/cdancy/jenkins/rest/domain/user/ApiToken.java
new file mode 100644
index 00000000..b6bfe01d
--- /dev/null
+++ b/src/main/java/com/cdancy/jenkins/rest/domain/user/ApiToken.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.cdancy.jenkins.rest.domain.user;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class ApiToken {
+
+    public abstract String status();
+
+    public abstract ApiTokenData data();
+
+    ApiToken() {
+    }
+
+    @SerializedNames({"status", "data"})
+    public static ApiToken create(final String status, final ApiTokenData data) {
+        return new AutoValue_ApiToken(status, data);
+    }
+}
diff --git a/src/main/java/com/cdancy/jenkins/rest/domain/user/ApiTokenData.java b/src/main/java/com/cdancy/jenkins/rest/domain/user/ApiTokenData.java
new file mode 100644
index 00000000..bb85d6f1
--- /dev/null
+++ b/src/main/java/com/cdancy/jenkins/rest/domain/user/ApiTokenData.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.cdancy.jenkins.rest.domain.user;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class ApiTokenData {
+
+    public abstract String tokenName();
+    public abstract String tokenUuid();
+    public abstract String tokenValue();
+
+    ApiTokenData() {
+    }
+
+    @SerializedNames({"tokenName", "tokenUuid", "tokenValue"})
+    public static ApiTokenData create(final String tokenName, final String tokenUuid, final String tokenValue) {
+        return new AutoValue_ApiTokenData(tokenName, tokenUuid, tokenValue);
+    }
+}
diff --git a/src/main/java/com/cdancy/jenkins/rest/domain/user/Property.java b/src/main/java/com/cdancy/jenkins/rest/domain/user/Property.java
new file mode 100644
index 00000000..1c3e99a2
--- /dev/null
+++ b/src/main/java/com/cdancy/jenkins/rest/domain/user/Property.java
@@ -0,0 +1,18 @@
+package com.cdancy.jenkins.rest.domain.user;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class Property {
+
+    public abstract String clazz();
+
+    Property() {
+    }
+
+    @SerializedNames({"_class"})
+    public static Property create(final String clazz) {
+        return new AutoValue_Property(clazz);
+    }
+}
diff --git a/src/main/java/com/cdancy/jenkins/rest/filters/JenkinsAuthenticationFilter.java b/src/main/java/com/cdancy/jenkins/rest/filters/JenkinsAuthenticationFilter.java
index e07c7bde..d3fc2940 100644
--- a/src/main/java/com/cdancy/jenkins/rest/filters/JenkinsAuthenticationFilter.java
+++ b/src/main/java/com/cdancy/jenkins/rest/filters/JenkinsAuthenticationFilter.java
@@ -51,14 +51,16 @@ public class JenkinsAuthenticationFilter implements HttpRequestFilter {
 
     @Override
     public HttpRequest filter(final HttpRequest request) throws HttpException {
-        if (creds.authType() == AuthenticationType.Anonymous) {
-            return request;
-        } else {
-            final String authHeader = creds.authType() + " " + creds.authValue();
-            final HttpRequest.Builder<? extends HttpRequest.Builder<?>> builder = request.toBuilder();
+        final HttpRequest.Builder<? extends HttpRequest.Builder<?>> builder = request.toBuilder();
+
+        // Password and API Token are both Basic authentication
+        if (creds.authType() == AuthenticationType.ApiToken || creds.authType() == AuthenticationType.UsernamePassword) {
+            final String authHeader = creds.authType().getAuthScheme() + " " + creds.authValue();
             builder.addHeader(HttpHeaders.AUTHORIZATION, authHeader);
+        }
 
-            // whether to add crumb header or not
+        // Anon and Password need the crumb
+        if (creds.authType() == AuthenticationType.UsernamePassword || creds.authType() == AuthenticationType.Anonymous) {
             final Pair<Crumb, Boolean> localCrumb = getCrumb();
             if (localCrumb.getKey().value() != null) {
                 builder.addHeader(CRUMB_HEADER, localCrumb.getKey().value());
@@ -69,9 +71,8 @@ public HttpRequest filter(final HttpRequest request) throws HttpException {
                     throw new RuntimeException("Unexpected exception being thrown: error=" + localCrumb.getKey().errors().get(0));
                 }
             }
-
-            return builder.build();
         }
+        return builder.build();
     }
 
     private Pair<Crumb, Boolean> getCrumb() {
diff --git a/src/main/java/com/cdancy/jenkins/rest/filters/JenkinsNoCrumbAuthenticationFilter.java b/src/main/java/com/cdancy/jenkins/rest/filters/JenkinsNoCrumbAuthenticationFilter.java
index 918e5697..2daa407a 100644
--- a/src/main/java/com/cdancy/jenkins/rest/filters/JenkinsNoCrumbAuthenticationFilter.java
+++ b/src/main/java/com/cdancy/jenkins/rest/filters/JenkinsNoCrumbAuthenticationFilter.java
@@ -43,7 +43,7 @@ public HttpRequest filter(final HttpRequest request) throws HttpException {
         if (creds.authType() == AuthenticationType.Anonymous) {
             return request;
         } else {
-            final String authHeader = creds.authType() + " " + creds.authValue();
+            final String authHeader = creds.authType().getAuthScheme() + " " + creds.authValue();
             return request.toBuilder().addHeader(HttpHeaders.AUTHORIZATION, authHeader).build();
         }
     }
diff --git a/src/test/java/com/cdancy/jenkins/rest/BaseJenkinsMockTest.java b/src/test/java/com/cdancy/jenkins/rest/BaseJenkinsMockTest.java
index f4d6195e..609efd6c 100644
--- a/src/test/java/com/cdancy/jenkins/rest/BaseJenkinsMockTest.java
+++ b/src/test/java/com/cdancy/jenkins/rest/BaseJenkinsMockTest.java
@@ -31,6 +31,7 @@
 import org.jclouds.ContextBuilder;
 
 import com.cdancy.jenkins.rest.config.JenkinsAuthenticationModule;
+import com.cdancy.jenkins.rest.auth.AuthenticationType;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Functions;
@@ -42,15 +43,22 @@
 import com.squareup.okhttp.mockwebserver.MockResponse;
 import com.squareup.okhttp.mockwebserver.MockWebServer;
 import com.squareup.okhttp.mockwebserver.RecordedRequest;
+import static com.google.common.io.BaseEncoding.base64;
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
 
 /**
  * Base class for all Jenkins mock tests.
  */
 public class BaseJenkinsMockTest {
 
+    public static final String USERNAME_PASSWORD = "user:passwd";
+    public static final String USERNAME_APITOKEN = "user:token";
+
     protected final String provider;
     private final JsonParser parser = new JsonParser();
 
@@ -65,18 +73,46 @@ public BaseJenkinsMockTest() {
      * @return instance of JenkinsApi.
      */
     public JenkinsApi api(final URL url) {
-        final JenkinsAuthentication creds = JenkinsAuthentication.builder().build();
+        return api(url, AuthenticationType.ApiToken);
+    }
+
+    /**
+     * Create API from passed URL and passed authentication type.
+     *
+     * @param url endpoint of instance.
+     * @param authType authentication type.
+     */
+    public JenkinsApi api(final URL url, final AuthenticationType authType) {
+        final JenkinsAuthentication creds = creds(authType);
         final JenkinsAuthenticationModule credsModule = new JenkinsAuthenticationModule(creds);
         return ContextBuilder.newBuilder(provider)
                 .endpoint(url.toString())
                 .overrides(setupProperties())
-                .modules(Lists.newArrayList(credsModule))
+                .modules(Lists.newArrayList(credsModule, new SLF4JLoggingModule()))
                 .buildApi(JenkinsApi.class);
     }
 
+    /**
+     * Create the Jenkins Authentication instance.
+     *
+     * @param authType authentication type. Falls back to anonymous when null.
+     * @return an authenticaition instance.
+     */
+    public JenkinsAuthentication creds(final AuthenticationType authType) {
+        final JenkinsAuthentication.Builder authBuilder = JenkinsAuthentication.builder();
+        if (authType == AuthenticationType.UsernamePassword) {
+            authBuilder.credentials(USERNAME_PASSWORD);
+        } else if (authType == AuthenticationType.ApiToken) {
+            authBuilder.apiToken(USERNAME_APITOKEN);
+        }
+        // Anonymous authentication is the default when not specified
+        return authBuilder.build();
+    }
+
     protected Properties setupProperties() {
         final Properties properties = new Properties();
         properties.setProperty(Constants.PROPERTY_MAX_RETRIES, "0");
+        properties.setProperty(Constants.PROPERTY_CONNECTION_TIMEOUT, "1");
         return properties;
     }
 
@@ -215,4 +251,16 @@ protected RecordedRequest assertSent(MockWebServer server, String method, String
         assertEquals(parser.parse(request.getUtf8Body()), parser.parse(json));
         return request;
     }
+
+    protected RecordedRequest assertSentAcceptAuth(MockWebServer server, String method, String path, String acceptType, AuthenticationType authType) throws InterruptedException {
+        RecordedRequest request = assertSentAccept(server, method, path, acceptType);
+        if (authType == AuthenticationType.UsernamePassword) {
+            assertEquals(request.getHeader("Authorization"), authType.getAuthScheme() + " " + base64().encode(USERNAME_PASSWORD.getBytes()));
+        } else if (authType == AuthenticationType.ApiToken) {
+            assertEquals(request.getHeader("Authorization"), authType.getAuthScheme() + " " + base64().encode(USERNAME_APITOKEN.getBytes()));
+        } else {
+            assertNull(request.getHeader("Authorization"));
+        }
+        return request;
+    }
 }
diff --git a/src/test/java/com/cdancy/jenkins/rest/TestUtilities.java b/src/test/java/com/cdancy/jenkins/rest/TestUtilities.java
index bbae21d7..1fa84aa7 100644
--- a/src/test/java/com/cdancy/jenkins/rest/TestUtilities.java
+++ b/src/test/java/com/cdancy/jenkins/rest/TestUtilities.java
@@ -43,8 +43,8 @@ public class TestUtilities extends JenkinsUtils {
     public static final String TEST_CREDENTIALS_SYSTEM_PROPERTY = "test.jenkins.rest.credentials";
     public static final String TEST_CREDENTIALS_ENVIRONMENT_VARIABLE = TEST_CREDENTIALS_SYSTEM_PROPERTY.replaceAll("\\.", "_").toUpperCase();
 
-    public static final String TEST_TOKEN_SYSTEM_PROPERTY = "test.jenkins.rest.token";
-    public static final String TEST_TOKEN_ENVIRONMENT_VARIABLE = TEST_TOKEN_SYSTEM_PROPERTY.replaceAll("\\.", "_").toUpperCase();
+    public static final String TEST_API_TOKEN_SYSTEM_PROPERTY = "test.jenkins.rest.api.token";
+    public static final String TEST_API_TOKEN_ENVIRONMENT_VARIABLE = TEST_API_TOKEN_SYSTEM_PROPERTY.replaceAll("\\.", "_").toUpperCase();
 
     private static final char[] CHARS = "abcdefghijklmnopqrstuvwxyz".toCharArray();
 
@@ -73,28 +73,30 @@ public static String randomString() {
     }
 
     /**
-     * Find credentials (Basic, Bearer, or Anonymous) from system/environment.
+     * Find credentials (ApiToken, UsernamePassword, or Anonymous) from system/environment.
      *
      * @return JenkinsCredentials
      */
     public static JenkinsAuthentication inferTestAuthentication() {
 
-        // 1.) Check for "Basic" auth credentials.
         final JenkinsAuthentication.Builder inferAuth = JenkinsAuthentication.builder();
+
+        // 1.) Check for API Token as this requires no crumb hence is faster
         String authValue = JenkinsUtils
+                .retriveExternalValue(TEST_API_TOKEN_SYSTEM_PROPERTY,
+                        TEST_API_TOKEN_ENVIRONMENT_VARIABLE);
+        if (authValue != null) {
+            inferAuth.apiToken(authValue);
+            return inferAuth.build();
+        }
+
+        // 2.) Check for UsernamePassword auth credentials.
+        authValue = JenkinsUtils
                 .retriveExternalValue(TEST_CREDENTIALS_SYSTEM_PROPERTY,
                         TEST_CREDENTIALS_ENVIRONMENT_VARIABLE);
         if (authValue != null) {
             inferAuth.credentials(authValue);
-        } else {
-
-            // 2.) Check for "Bearer" auth token.
-            authValue = JenkinsUtils
-                    .retriveExternalValue(TEST_TOKEN_SYSTEM_PROPERTY,
-                            TEST_TOKEN_ENVIRONMENT_VARIABLE);
-            if (authValue != null) {
-                inferAuth.token(authValue);
-            }
+            return inferAuth.build();
         }
 
         // 3.) If neither #1 or #2 find anything "Anonymous" access is assumed.
diff --git a/src/test/java/com/cdancy/jenkins/rest/filters/JenkinsAuthenticationFilterMockTest.java b/src/test/java/com/cdancy/jenkins/rest/filters/JenkinsAuthenticationFilterMockTest.java
new file mode 100644
index 00000000..9b522c96
--- /dev/null
+++ b/src/test/java/com/cdancy/jenkins/rest/filters/JenkinsAuthenticationFilterMockTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cdancy.jenkins.rest.filters;
+
+import javax.ws.rs.core.MediaType;
+
+import com.cdancy.jenkins.rest.JenkinsApi;
+import com.cdancy.jenkins.rest.JenkinsAuthentication;
+import com.cdancy.jenkins.rest.auth.AuthenticationType;
+import com.cdancy.jenkins.rest.BaseJenkinsMockTest;
+
+import org.jclouds.http.HttpRequest;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import com.google.common.collect.Multimap;
+
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+
+public class JenkinsAuthenticationFilterMockTest extends BaseJenkinsMockTest {
+
+    @Test
+    public void testAnonymousNeedsCrumb() throws Exception {
+        MockWebServer server = mockWebServer();
+
+        final String value = "04a1109fc2db171362c966ebe9fc87f0";
+        server.enqueue(new MockResponse().setBody("Jenkins-Crumb:" + value).setResponseCode(200));
+        JenkinsApi jenkinsApi = api(server.getUrl("/"), AuthenticationType.Anonymous);
+
+        JenkinsAuthentication creds = creds(AuthenticationType.Anonymous);
+        JenkinsAuthenticationFilter filter = new JenkinsAuthenticationFilter(creds, jenkinsApi);
+        HttpRequest httpRequest = HttpRequest.builder().endpoint(server.getUrl("/").toString()).method("GET").build();
+        try {
+            httpRequest = filter.filter(httpRequest);
+            assertSentAcceptAuth(server, "GET", "/crumbIssuer/api/xml?xpath=concat%28//crumbRequestField,%22%3A%22,//crumb%29", MediaType.TEXT_PLAIN, AuthenticationType.Anonymous);
+            assertEquals(httpRequest.getEndpoint().toString(), server.getUrl("/").toString());
+            Multimap<String,String> headers = httpRequest.getHeaders();
+            assertEquals(headers.size(), 2);
+            assertTrue(headers.containsEntry("Jenkins-Crumb",value));
+            assertTrue(headers.containsEntry("Cookie",""));
+        } finally {
+            jenkinsApi.close();
+            server.shutdown();
+        }
+    }
+
+    @Test
+    public void testUsernamePasswordNeedsCrumb() throws Exception {
+        MockWebServer server = mockWebServer();
+
+        final String value = "04a1109fc2db171362c966ebe9fc87f0";
+        server.enqueue(new MockResponse().setBody("Jenkins-Crumb:" + value).setResponseCode(200));
+        JenkinsApi jenkinsApi = api(server.getUrl("/"), AuthenticationType.UsernamePassword);
+
+        JenkinsAuthentication creds = creds(AuthenticationType.UsernamePassword);
+        JenkinsAuthenticationFilter filter = new JenkinsAuthenticationFilter(creds, jenkinsApi);
+        HttpRequest httpRequest = HttpRequest.builder().endpoint(server.getUrl("/").toString()).method("GET").build();
+        try {
+            httpRequest = filter.filter(httpRequest);
+            assertSentAcceptAuth(server, "GET", "/crumbIssuer/api/xml?xpath=concat%28//crumbRequestField,%22%3A%22,//crumb%29", MediaType.TEXT_PLAIN, AuthenticationType.UsernamePassword);
+            assertEquals(httpRequest.getEndpoint().toString(), server.getUrl("/").toString());
+            Multimap<String,String> headers = httpRequest.getHeaders();
+            assertEquals(headers.size(), 3);
+            assertTrue(headers.containsEntry("Jenkins-Crumb",value));
+            assertTrue(headers.containsEntry("Authorization", creds.authType().getAuthScheme() + " " + creds.authValue()));
+            assertTrue(headers.containsEntry("Cookie",""));
+            System.out.println(httpRequest.toString());
+        } finally {
+            jenkinsApi.close();
+            server.shutdown();
+        }
+    }
+
+    @Test
+    public void testFilterApiTokenAuthType() throws Exception {
+        MockWebServer server = mockWebServer();
+
+        JenkinsApi jenkinsApi = api(server.getUrl("/"), AuthenticationType.ApiToken);
+
+        JenkinsAuthentication creds = creds(AuthenticationType.ApiToken);
+        JenkinsAuthenticationFilter filter = new JenkinsAuthenticationFilter(creds, jenkinsApi);
+        HttpRequest httpRequest = HttpRequest.builder().endpoint(server.getUrl("/").toString()).method("GET").build();
+        try {
+            httpRequest = filter.filter(httpRequest);
+            assertEquals(httpRequest.getEndpoint().toString(), server.getUrl("/").toString());
+            System.out.println(httpRequest.toString());
+            Multimap<String,String> headers = httpRequest.getHeaders();
+            assertEquals(headers.size(), 1);
+            assertTrue(headers.containsEntry("Authorization", creds.authType().getAuthScheme() + " " + creds.authValue()));
+        } finally {
+            jenkinsApi.close();
+            server.shutdown();
+        }
+    }
+}