Java client for the Xproapi X (Twitter) data API. Java 11+, no dependencies.
With Maven, through JitPack (builds the GitHub repository):
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.github.Xproapi-LLC</groupId>
<artifactId>xproapi_java</artifactId>
<version>master-SNAPSHOT</version>
</dependency>With Gradle: add maven { url 'https://jitpack.io' } to repositories and implementation 'com.github.Xproapi-LLC:xproapi_java:master-SNAPSHOT' to dependencies.
Or build the jar yourself and add it to your classpath:
git clone https://github.com/Xproapi-LLC/xproapi_java.git
cd xproapi_java && mvn package # target/xproapi-1.0.0.jarimport com.xproapi.Xproapi;
import java.util.List;
import java.util.Map;
Xproapi x = new Xproapi(System.getenv("XPROAPI_KEY"));
Map<String, Object> user = (Map<String, Object>) x.userInfo("jack").get("data");
System.out.printf("%s has %,d followers%n", user.get("name"), user.get("followers"));
// One page (up to 200), then the next
Map<String, Object> page = x.followers("jack", Map.of("pageSize", 200));
Map<String, Object> next = x.followers("jack", Map.of("cursor", page.get("next_cursor")));
// Every page, capped at 5 requests
for (Map<String, Object> follower : x.paginate("followers", Map.of("userName", "jack"), 5)) {
System.out.println(follower.get("userName"));
}
// Tweets
x.lastTweets(Map.of("userName", "jack", "includeReplies", false));
x.advancedSearch("from:jack min_faves:100", Map.of("queryType", "Top"));
x.tweetsByIds(List.of("20", "1800000000000000000"));
x.replies("https://x.com/jack/status/20"); // ids or linksMethods return the API's JSON as Map<String, Object> (lists are List<Object>, whole numbers Long, others Double). Optional parameters go in a Map under the API's own names (cursor, pageSize, queryType…); every method also has a version without it.
Xproapi x = Xproapi.builder("xp_...")
.baseUrl("https://xproapi.com/api") // default
.timeout(Duration.ofSeconds(30)) // per request
.maxRetries(2) // for 429 / 502 / 503 / network errors; 0 = off
.build();.transport(...) replaces the built-in java.net.http.HttpClient (proxies, tests).
import com.xproapi.*;
try {
x.userInfo("someone");
} catch (NotFoundException e) {
// no such user
} catch (InsufficientCreditsException e) {
// top up; nothing was charged
} catch (RateLimitException e) {
Thread.sleep(e.getRetryAfter() * 1000L);
} catch (XproapiException e) {
System.err.println("Xproapi " + e.getStatus() + ": " + e.getMessage());
}The exceptions are unchecked. BadRequestException (400), AuthenticationException (401), InsufficientCreditsException (402), PermissionDeniedException (403), NotFoundException (404), RateLimitException (429) and ServiceUnavailableException (5xx) all extend XproapiException. Network failures throw the base class with status 0.
x.rateLimit().limit; // 60, from the last response (null before the first)
x.rateLimit().remaining; // 57x.get("/twitter/user/info", Map.of("userName", "jack")) calls any GET endpoint with the same auth, retries and errors.
The offline tests need only a JDK (no test framework):
javac -d target/classes $(find src/main/java -name "*.java")
javac -d target/test-classes -cp target/classes tests/com/xproapi/ClientTest.java
java -cp "target/classes:target/test-classes" com.xproapi.ClientTest # on Windows use ; instead of :