The official Java SDK. Java 11+, built on java.net.http.HttpClient, single
dependency (Jackson), Jackson JsonNode responses with a fluent params builder.
Or OmniSocials.fromEnv() (reads OMNISOCIALS_API_KEY). A missing key throws
AuthenticationException.
Create a post
Code
JsonNode res = client.posts().create(Params.builder() .put("content", "New drop this Friday") .put("channels", List.of("instagram", "facebook", "linkedin")) .put("scheduled_at", "2026-08-01T09:00:00Z") .put("media_urls", List.of("https://example.com/teaser.jpg")) .build());JsonNode post = res.get("data");System.out.println(post.get("id").asText() + " " + post.get("status").asText());
Any media_urls (or media_ids) entry can also be a map carrying per-media
alt text (max 1500 chars), delivered to Mastodon, Bluesky, X (photos/GIFs), and
Pinterest:
Code
.put("media_urls", List.of(Params.of( "url", "https://example.com/teaser.jpg", "alt", "Red sneaker on a white background")))
Publish immediately:
Code
client.posts().createAndPublish(Params.builder() .put("content", "Going live right now") .put("channels", List.of("x", "bluesky")) .build());
import java.nio.file.Path;// From a path (filename and content type detected from the file)JsonNode res = client.media().upload(Path.of("photos/product.jpg"), Params.of("name", "product-hero"));// Or from bytes + filenamebyte[] bytes = java.nio.file.Files.readAllBytes(Path.of("photos/product.jpg"));client.media().upload(bytes, "product.jpg");
Analytics
Code
// One post's latest per-platform metricsJsonNode stats = client.analytics().post("post_id");System.out.println(stats.get("data").get("platforms").path("instagram").path("metrics"));// Batch: up to 100 posts in one callJsonNode batch = client.analytics().posts(List.of("id1", "id2", "id3"));// or: client.analytics().posts("id1", "id2", "id3");// Workspace-wide overviewJsonNode overview = client.analytics().overview(Params.of("period", "30d"));System.out.println(overview.get("data").get("total_impressions").asLong());// Account-level stats (followers etc)JsonNode accountStats = client.analytics().accounts(Params.of("platform", "instagram"));
Verify webhooks
Spring Boot:
Code
import com.fasterxml.jackson.databind.JsonNode;import com.omnisocials.Webhooks;import com.omnisocials.errors.WebhookVerificationException;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestHeader;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class OmniSocialsWebhookController { private final String secret = System.getenv("OMNISOCIALS_WEBHOOK_SECRET"); @PostMapping("/omnisocials/webhook") public ResponseEntity<Void> handle( @RequestBody String rawBody, // Spring gives you the raw body as a String @RequestHeader("X-OmniSocials-Signature") String signature) { JsonNode event; try { event = Webhooks.verifySignature(rawBody, signature, secret, 300); } catch (WebhookVerificationException e) { return ResponseEntity.badRequest().build(); } switch (event.get("type").asText()) { case "post.published": System.out.println("Published: " + event.get("data").get("post_id").asText()); break; case "post.failed": System.err.println("Failed: " + event.get("data").get("post_id").asText()); break; default: break; } return ResponseEntity.ok().build(); }}
Errors
All exceptions extend OmniSocialsException (unchecked) and live in
com.omnisocials.errors. ApiException exposes getStatus(), getCode(),
getMessage(), and getBody(). Types: ValidationException (400/422),
AuthenticationException (401), PermissionDeniedException (403),
NotFoundException (404), RateLimitException (429, getRetryAfter()),
ServerException (5xx), ApiConnectionException, WebhookVerificationException.