Java SDK
Official Java client for the Moorsyl API.
The Moorsyl Java SDK provides typed request/response models for all API endpoints and supports Java 8+.
- Maven Central — com.moorsyl:moorsyl-java
- Source — github.com/SoftwareSavants/moorsyl-java
Installation
Maven
<dependency>
<groupId>com.moorsyl</groupId>
<artifactId>moorsyl-java</artifactId>
<version>1.0.3</version>
</dependency>Gradle
implementation 'com.moorsyl:moorsyl-java:1.0.3'Initialization
import com.moorsyl.ApiClient;
import com.moorsyl.api.SmsApi;
import com.moorsyl.api.VerifyApi;
ApiClient client = new ApiClient();
client.setApiKey("sk_live_...");
SmsApi sms = new SmsApi(client);
VerifyApi verify = new VerifyApi(client);The SDK defaults to https://api.moorsyl.com/api. Override with client.setBasePath(...) if needed.
Send an SMS
Requires a secret key (sk_…). See API Keys.
import com.moorsyl.ApiClient;
import com.moorsyl.api.SmsApi;
import com.moorsyl.model.SmsSendRequest;
import com.moorsyl.model.SmsSend200Response;
ApiClient client = new ApiClient();
client.setApiKey("sk_live_...");
SmsApi sms = new SmsApi(client);
SmsSendRequest request = new SmsSendRequest()
.to("+22236551999")
.from("MyBrand")
.body("Your order #1042 has been shipped.");
SmsSend200Response response = sms.smsSend(request);
System.out.println("Accepted: " + response.getAccepted());
System.out.println("Message ID: " + response.getMessageId());
System.out.println("Idempotency key: " + response.getIdempotencyKey());Supply idempotencyKey to prevent duplicate sends on retries:
SmsSendRequest request = new SmsSendRequest()
.to("+22236551999")
.from("MyBrand")
.body("Your code is 847291")
.idempotencyKey("otp-user42-20240101T120000");
sms.smsSend(request);Phone Verification
Use a publishable key (pk_…) so this code can run safely in client-facing contexts. See API Keys.
import com.moorsyl.ApiClient;
import com.moorsyl.api.VerifyApi;
ApiClient client = new ApiClient();
client.setApiKey("pk_live_...");
VerifyApi verify = new VerifyApi(client);Send a verification code
import com.moorsyl.model.VerifySendRequest;
import com.moorsyl.model.VerifySend200Response;
VerifySend200Response sendResponse = verify.verifySend(
new VerifySendRequest().to("+22236551999")
);
String verificationId = sendResponse.getVerificationId();Check the code
import com.moorsyl.model.VerifyCheckRequest;
import com.moorsyl.model.VerifyCheck200Response;
VerifyCheck200Response checkResponse = verify.verifyCheck(
new VerifyCheckRequest()
.verificationId(verificationId)
.code(userEnteredCode)
);
if (checkResponse.getStatus() == VerifyCheck200Response.StatusEnum.APPROVED) {
// phone is verified — proceed
}Full flow
import com.moorsyl.ApiClient;
import com.moorsyl.api.VerifyApi;
import com.moorsyl.model.*;
public class PhoneVerification {
public static boolean verifyPhoneNumber(String phoneNumber, String userCode) throws Exception {
ApiClient client = new ApiClient();
client.setApiKey("pk_live_...");
VerifyApi verify = new VerifyApi(client);
// Step 1 — send the code
VerifySend200Response sendResponse = verify.verifySend(
new VerifySendRequest().to(phoneNumber)
);
// Step 2 — check the code the user entered
VerifyCheck200Response checkResponse = verify.verifyCheck(
new VerifyCheckRequest()
.verificationId(sendResponse.getVerificationId())
.code(userCode)
);
return checkResponse.getStatus() == VerifyCheck200Response.StatusEnum.APPROVED;
}
}Error handling
API methods throw ApiException on non-2xx responses:
import com.moorsyl.ApiException;
try {
sms.smsSend(new SmsSendRequest()
.to("+22236551999")
.from("MyBrand")
.body("Hello!"));
} catch (ApiException e) {
System.out.println("Status: " + e.getCode());
System.out.println("Body: " + e.getResponseBody());
}Common status codes are documented on the SMS and Verify pages.
Webhook signature verification
Verify incoming webhook signatures to ensure requests are genuine. See Webhooks.
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.util.Base64;
public class WebhookVerifier {
public static boolean verify(String rawBody, String header, String secret) {
try {
String[] pairs = header.split(",");
String timestamp = null, signature = null;
for (String pair : pairs) {
String[] kv = pair.split("=", 2);
if ("t".equals(kv[0])) timestamp = kv[1];
if ("v1".equals(kv[0])) signature = kv[1];
}
if (timestamp == null || signature == null) return false;
long age = System.currentTimeMillis() / 1000 - Long.parseLong(timestamp);
if (age > 300) return false;
byte[] keyBytes = Base64.getDecoder().decode(secret.replace("whsec_", ""));
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(keyBytes, "HmacSHA256"));
byte[] hash = mac.doFinal((timestamp + "." + rawBody).getBytes());
String expected = bytesToHex(hash);
return MessageDigest.isEqual(expected.getBytes(), signature.getBytes());
} catch (Exception e) {
return false;
}
}
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) sb.append(String.format("%02x", b));
return sb.toString();
}
}Requirements
- Java 8+
- Maven 2.2+ or Gradle