Java client for the QubitOn API by QubitOn. Validates addresses, tax IDs, and bank accounts; looks up business registrations; screens for sanctions, PEPs, and disqualified directors; and exposes 40+ enrichment endpoints across 250+ countries.
Note:
0.1.0-SNAPSHOTis the development coordinate. For published releases, replace0.1.0-SNAPSHOTwith the latest released version (e.g.0.1.0) once it's on Maven Central.
<dependency>
<groupId>com.qubiton</groupId>
<artifactId>qubiton-sdk</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>Gradle:
implementation("com.qubiton:qubiton-sdk:0.1.0-SNAPSHOT")import com.qubiton.sdk.QubitOnClient;
import com.qubiton.sdk.QubitOnEnvironment;
import com.qubiton.sdk.models.Address;
QubitOnClient client = QubitOnClient.builder()
.apiKey("qbtn_...")
.environment(QubitOnEnvironment.PROD)
.build();
Address.AddressRequest req = Address.AddressRequest.builder()
.country("US")
.addressLine1("123 Main St")
.city("New York")
.state("NY")
.postalCode("10001")
.build();
Address.AddressResponse resp = client.validateAddress(req);
System.out.println("Standardised: " + resp.getAddress1() + ", " + resp.getCity());The SDK supports two auth modes — pick exactly one. The builder validates this at build().
QubitOnClient client = QubitOnClient.builder()
.apiKey("qbtn_...")
.build();The header name is the lowercase string apikey — not X-Api-Key. The .NET backend rejects the latter.
QubitOnClient client = QubitOnClient.builder()
.clientCredentials("subscription-key", "consumer-secret")
.build();The SDK calls POST /api/oauth/token with {"key": "...", "secret": "..."} and caches the returned JWE token until 30s before expiry. On any 401 with a previously valid token the SDK invalidates the cache and retries the request once.
Note: this is not standard OAuth 2.0 client_credentials. The endpoint contract is QubitOn-specific.
Every call has a *Async variant returning CompletableFuture:
client.validateAddressAsync(req)
.thenAccept(resp -> System.out.println(resp.getAddress1()))
.exceptionally(err -> { err.printStackTrace(); return null; });QubitOnClient client = QubitOnClient.builder()
.apiKey("qbtn_...")
.environment(QubitOnEnvironment.PROD) // or .baseUrl("...")
.connectTimeout(Duration.ofSeconds(10)) // default: 10s
.requestTimeout(Duration.ofSeconds(30)) // default: 30s (per HTTP request)
.maxAttempts(3) // default: 3 (1 initial + 2 retries)
.maxBackoff(Duration.ofSeconds(30)) // default: 30s hard cap on retry delay
.httpClient(myHttpClient) // optional injection
.objectMapper(myObjectMapper) // optional injection
.proxy(ProxySelector.of(InetSocketAddress.createUnresolved("proxy", 8080)))
.proxyAuth(myProxyAuthenticator) // optional — only effective when proxy(...) is set
.build();| Setting | Default |
|---|---|
connectTimeout |
10s |
requestTimeout |
30s |
maxAttempts |
3 (1 initial + 2 retries) |
maxBackoff |
30s |
environment |
QubitOnEnvironment.PROD |
| Available environments | PROD, STAGING, QA, DEV, LOCAL |
The client exposes 50+ endpoints across these domains (40+ enrichment endpoints plus bulk submit/pickup pairs):
| Domain | Methods |
|---|---|
| Address | validateAddress |
| Tax | validateTax, validateTaxFormat, getSupportedTaxFormats |
| Bank | validateBankAccount, validateBankPro |
| Email & phone | validateEmail, validatePhone |
| Business registration | lookupBusinessRegistration |
| Peppol | validatePeppol, getPeppolSchemes |
| Sanctions / PEP / directors | checkSanctions, screenPEP, checkDirectors |
| EPA prosecution | checkEPAProsecution, lookupEPAProsecution |
| Healthcare exclusion | checkHealthcareExclusion, lookupHealthcareExclusion |
| Risk | checkBankruptcyRisk, lookupCreditScore, lookupFailRate, assessEntityRisk, lookupCreditAnalysis |
| ESG & cybersecurity | lookupESGScore, domainSecurityReport, checkIPQuality |
| Corporate structure | lookupBeneficialOwnership, lookupCorporateHierarchy, lookupDUNS, lookupHierarchy |
| Industry | validateNPI, validateMedpass, lookupDOTCarrier, validateIndiaIdentity |
| Certification | validateCertification, lookupCertification |
| Business classification | lookupBusinessClassification |
| Financial ops | analyzePaymentTerms, lookupExchangeRates |
| Ariba supplier | lookupAribaSupplier, validateAribaSupplier |
| Gender | identifyGender |
| Bulk / continuous | screenContinuous, checkBulkStatus, submitBulkAddressValidate/pickupBulkAddressValidate, submitBulkBankProValidate/pickupBulkBankProValidate, submitBulkTaxValidate/pickupBulkTaxValidate, submitBulkSmartVmDataLookup/pickupBulkSmartVmDataLookup |
DTO field names follow the canonical .NET request models. A few load-bearing examples:
Tax.TaxRequestusesidentityNumberandidentityNumberType(NOTtaxNumber/taxType).BusinessRegistration.BusinessRegistrationRequestusesentityName(NOTcompanyName).Sanctions.SanctionsRequestusescompanyNamefor entity screening; person fields are separate (firstName/lastName).Directors.DirectorsRequesttakes person fields, not company fields.Bank.BankRequestis the single-shape standard request. The pro endpoint uses a separateBank.BankAccountProRequest(sent to/api/bankaccount/pro/validate) and returnsBank.BankAccountProResponse, which carries the bank address (bankAddress), score/matchCode/threshold, IBAN, SWIFT, holder info, and the rawbankProValidationsanalytics map.
import com.qubiton.sdk.exceptions.*;
try {
Address.AddressResponse resp = client.validateAddress(req);
} catch (QubitonRateLimitException e) {
System.out.println("Rate-limited; retry after " + e.getRetryAfterSeconds() + "s");
} catch (QubitonAuthException e) {
System.out.println("Auth failed: " + e.getMessage());
} catch (QubitonNotFoundException e) {
System.out.println("Not found");
} catch (QubitonValidationException e) {
System.out.println("Bad request [" + e.getStatusCode() + "]: " + e.getMessage());
} catch (QubitonServerException e) {
System.out.println("Server error after retries");
} catch (QubitonException e) {
System.out.println("Other API error [" + e.getStatusCode() + "]: " + e.getMessage());
}The server's {"error": "...", "statusCode": N} envelope is parsed; getRaw() exposes the full parsed body for fields the SDK does not surface.
- Status codes retried:
408,429,500–599except501 Not Implemented(terminal — retrying won't help). - Up to 3 attempts with exponential backoff (base × 2^attempt) and ±25% jitter, capped at 30s.
Retry-After(delta-seconds or RFC 1123 HTTP-date) is honoured as a floor.429and 5xx final failures throw a typed exception; the parsed envelope is preserved.501is surfaced immediately as aQubitonServerExceptionand is not retried.408failures (after retries are exhausted) are surfaced as a genericQubitonException(the underlyingHttpTimeoutExceptioncause is also wrapped with status0).- On any 401 with a configured token manager, the cached token is invalidated and the request is retried once with a fresh token. The retry is "free" — it does not consume one of the configured
maxAttemptsretry slots.
- Java 11+
- Jackson Databind 2.18 (transitive)
mvn package -DskipTestsProduces target/qubiton-sdk-<version>.jar, sources jar, and javadoc jar.
This API also ships as a Model Context Protocol server.
- Manifest: https://mcp.qubiton.com/.well-known/mcp.json
- 39 tools, 20 prompts, 7 resources.
- Sign up at www.qubiton.com.
- Dashboard → API Keys.
- Copy your key (begins with
qbtn_).
MIT