Java Spring Examples
VerifNow provides an official Spring Boot SDK to simplify integration. You can also call the API directly with RestTemplate or WebClient.
Official SDK: 📦 verifnow-spring — Spring Boot starter for VerifNow 📖 Full example project — A complete working example
Option 1: Using the official SDK (recommended)
Add the dependency
<!-- pom.xml -->
<dependency>
<groupId>io.verifnow</groupId>
<artifactId>verifnow-spring</artifactId>
<version>2.1.0</version>
</dependency>Configure your API key
# application.properties
verifnow.api-key=${VERIFNOW_API_KEY}Use it in your service
The SDK provides auto-configured beans that you can inject directly. See the full documentation and usage examples at:
- 📦 SDK: github.com/verifnowio/verifnow-spring
- 📖 Example project: github.com/verifnowio/validation-java-example
Option 2: Direct API call with RestTemplate
If you prefer not to use the SDK, you can call the API directly.
Configuration
Add your API key to application.properties:
# application.properties
verifnow.api-key=${VERIFNOW_API_KEY}
verifnow.base-url=https://api.verifnow.io/api/v1/validateModel classes
// ValidationResult.java
package io.verifnow.client.model;
import com.fasterxml.jackson.annotation.JsonProperty;
public class ValidationResult {
private boolean valid;
private String message;
@JsonProperty("normalizedValue")
private String normalizedValue;
@JsonProperty("originalValue")
private String originalValue;
@JsonProperty("validationLevel")
private String validationLevel;
@JsonProperty("emailDetails")
private EmailDetails emailDetails;
public boolean isValid() { return valid; }
public String getMessage() { return message; }
public String getNormalizedValue() { return normalizedValue; }
public String getOriginalValue() { return originalValue; }
public String getValidationLevel() { return validationLevel; }
public EmailDetails getEmailDetails() { return emailDetails; }
}// EmailDetails.java
package io.verifnow.client.model;
import com.fasterxml.jackson.annotation.JsonProperty;
public class EmailDetails {
private EmailSignals signals;
@JsonProperty("risk_score")
private int riskScore;
@JsonProperty("risk_level")
private String riskLevel;
private String deliverability;
@JsonProperty("applied_level")
private String appliedLevel;
public EmailSignals getSignals() { return signals; }
public int getRiskScore() { return riskScore; }
public String getRiskLevel() { return riskLevel; }
public String getDeliverability() { return deliverability; }
}// EmailSignals.java
package io.verifnow.client.model;
import com.fasterxml.jackson.annotation.JsonProperty;
public class EmailSignals {
@JsonProperty("syntax_valid")
private boolean syntaxValid;
@JsonProperty("mx_valid")
private boolean mxValid;
@JsonProperty("typo_detected")
private boolean typoDetected;
@JsonProperty("suggested_domain")
private String suggestedDomain;
private boolean disposable;
@JsonProperty("role_based")
private boolean roleBased;
@JsonProperty("free_provider")
private boolean freeProvider;
@JsonProperty("domain_age_days")
private Integer domainAgeDays;
@JsonProperty("mx_provider")
private String mxProvider;
@JsonProperty("mx_quality_score")
private double mxQualityScore;
public boolean isDisposable() { return disposable; }
public boolean isTypoDetected() { return typoDetected; }
public String getSuggestedDomain() { return suggestedDomain; }
public boolean isRoleBased() { return roleBased; }
public boolean isFreeProvider() { return freeProvider; }
public boolean isSyntaxValid() { return syntaxValid; }
public boolean isMxValid() { return mxValid; }
}Service
// VerifNowService.java
package io.verifnow.client.service;
import io.verifnow.client.model.ValidationResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Service
public class VerifNowService {
private static final Logger logger = LoggerFactory.getLogger(VerifNowService.class);
private final RestTemplate restTemplate;
@Value("${verifnow.api-key}")
private String apiKey;
@Value("${verifnow.base-url}")
private String baseUrl;
public VerifNowService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Retryable(
retryFor = { HttpClientErrorException.TooManyRequests.class },
maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2)
)
public ValidationResult validateEmail(String email) {
HttpHeaders headers = new HttpHeaders();
headers.set("X-API-KEY", apiKey);
headers.setContentType(MediaType.APPLICATION_JSON);
Map<String, String> body = Map.of("value", email);
HttpEntity<Map<String, String>> request = new HttpEntity<>(body, headers);
try {
ResponseEntity<ValidationResult> response = restTemplate.postForEntity(
baseUrl + "/email",
request,
ValidationResult.class
);
return response.getBody();
} catch (HttpClientErrorException.Unauthorized e) {
throw new RuntimeException("Invalid VerifNow API key. Check VERIFNOW_API_KEY.", e);
} catch (HttpClientErrorException.TooManyRequests e) {
logger.warn("VerifNow quota exceeded, retrying...");
throw e; // Let @Retryable handle it
} catch (HttpClientErrorException e) {
logger.error("VerifNow API error: {} {}", e.getStatusCode(), e.getMessage());
throw new RuntimeException("VerifNow validation failed: " + e.getMessage(), e);
}
}
}RestTemplate configuration
// AppConfig.java
package io.verifnow.client.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.web.client.RestTemplate;
@Configuration
@EnableRetry
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}Controller integration
// UserController.java
package io.verifnow.client.controller;
import io.verifnow.client.model.ValidationResult;
import io.verifnow.client.service.VerifNowService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/api/users")
public class UserController {
private final VerifNowService verifNowService;
public UserController(VerifNowService verifNowService) {
this.verifNowService = verifNowService;
}
@PostMapping("/register")
public ResponseEntity<?> register(@RequestBody Map<String, String> payload) {
String email = payload.get("email");
ValidationResult validation;
try {
validation = verifNowService.validateEmail(email);
} catch (Exception e) {
// Fail open: don't block registration if VerifNow is unreachable
return continueRegistration(email);
}
if (!validation.isValid()) {
String suggestion = "";
if (validation.getEmailDetails() != null
&& validation.getEmailDetails().getSignals() != null
&& validation.getEmailDetails().getSignals().getSuggestedDomain() != null) {
suggestion = validation.getEmailDetails().getSignals().getSuggestedDomain();
}
return ResponseEntity.badRequest().body(
Map.of(
"error", "Please provide a valid, reachable email address.",
"suggestion", suggestion
)
);
}
if (validation.getEmailDetails() != null
&& validation.getEmailDetails().getSignals() != null
&& validation.getEmailDetails().getSignals().isDisposable()) {
return ResponseEntity.badRequest().body(
Map.of("error", "Disposable email addresses are not allowed.")
);
}
return continueRegistration(email);
}
private ResponseEntity<?> continueRegistration(String email) {
// Your actual user creation logic here
return ResponseEntity.ok(Map.of("message", "Registration successful", "email", email));
}
}Reactive WebClient (Spring WebFlux)
For non-blocking, reactive applications:
// VerifNowReactiveService.java
package io.verifnow.client.service;
import io.verifnow.client.model.ValidationResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.util.Map;
@Service
public class VerifNowReactiveService {
private final WebClient webClient;
public VerifNowReactiveService(
@Value("${verifnow.api-key}") String apiKey,
@Value("${verifnow.base-url}") String baseUrl
) {
this.webClient = WebClient.builder()
.baseUrl(baseUrl)
.defaultHeader("X-API-KEY", apiKey)
.defaultHeader("Content-Type", "application/json")
.build();
}
public Mono<ValidationResult> validateEmail(String email) {
return webClient.post()
.uri("/email")
.bodyValue(Map.of("value", email))
.retrieve()
.onStatus(
status -> status.value() == 429,
response -> Mono.error(new RuntimeException("Quota exceeded"))
)
.bodyToMono(ValidationResult.class);
}
}Last updated on