Spring Boot

The FoPost Java client as a Spring Boot starter, with properties, actuator health, and webhook events.

com.fopost:fopost-spring-boot-starter is a thin wrapper over the Java SDK. Every request, retry, model, and error type lives there; the starter only wires it into Spring Boot: a configured client bean, fopost.* properties with IDE autocomplete, an actuator health entry, and inbound webhooks turned into application events.

Needs Java 17 and Spring Boot 3.

<dependency>
  <groupId>com.fopost</groupId>
  <artifactId>fopost-spring-boot-starter</artifactId>
  <version>0.1.0</version>
</dependency>
implementation("com.fopost:fopost-spring-boot-starter:0.1.0")

This is a 0.x release. The surface is still settling and a minor version may break something. Pin an exact version if that matters to you.

Published on Maven Central. Source and issues: github.com/fopost/fopost-spring. MIT licensed.

Configuration

Set a key and you have a client. Nothing is registered until fopost.api-key is present, so the starter is inert on a classpath that merely happens to contain it.

fopost:
  api-key: ${FOPOST_API_KEY} # required; sent as X-API-Key
  base-url: https://api.fopost.com # default
  timeout: 30s # default
  max-retries: 3 # default: total attempts, so two retries
  default-workspace-id: ws_123 # optional, for your own code to read
  webhook-secret: ${FOPOST_WEBHOOK_SECRET} # required only when receiving webhooks
  webhook:
    enabled: false # default
    path: /fopost/webhooks # default

Every key ships configuration metadata, so an IDE completes and documents them in application.yml and application.properties.

PropertyDefaultWhat it does
fopost.api-keynone, requiredAPI key from Settings → API Keys
fopost.base-urlhttps://api.fopost.comAPI root
fopost.timeout30sHow long one request may take
fopost.max-retries3Total attempts for a rate limited request
fopost.default-workspace-idnoneWorkspace your code falls back to
fopost.webhook-secretnoneSigning secret for inbound deliveries
fopost.webhook.enabledfalseMap the webhook controller
fopost.webhook.path/fopost/webhooksWhere it listens
management.health.fopost.enabledtrueContribute the actuator health entry

A blank fopost.api-key, usually an environment variable that never got set, fails the context at startup instead of at the first call.

Quick start

Inject FoPost anywhere. It is a singleton, immutable, and safe to share across threads.

import com.fopost.sdk.FoPost;
import com.fopost.sdk.model.Account;
import com.fopost.sdk.model.Post;
import com.fopost.sdk.param.CreatePostParams;

@Service
class Announcements {

    private final FoPost fopost;

    Announcements(FoPost fopost) {
        this.fopost = fopost;
    }

    String publish(String workspaceId, String text) {
        List<String> accounts =
                fopost.accounts().list(workspaceId).stream().map(Account::id).toList();

        Post post = fopost.posts()
                .create(CreatePostParams.of(workspaceId).content(text).accounts(accounts));

        fopost.posts().publish(post.id());
        return post.id();
    }
}

Declare your own FoPost bean and the starter backs off, so an unusual setup (a custom transport, a proxy, one client per tenant) needs no fighting with the auto-configuration.

The full resource surface (posts, accounts, workspaces, labels, webhooks, analytics, automations, media, ai), pagination, error types, and the request escape hatch are on the Java SDK page.

Receiving webhooks

Turn the endpoint on and give it the signing secret the create call returned:

fopost:
  webhook-secret: ${FOPOST_WEBHOOK_SECRET}
  webhook:
    enabled: true
    path: /fopost/webhooks

The controller verifies X-FoPost-Signature (HMAC-SHA256 over the raw request body, compared in constant time) and republishes the delivery on the application event bus. A body the secret does not sign is a 401 and never reaches a listener.

@Component
class Deliveries {

    @EventListener
    void onPublished(FoPostPostPublishedEvent event) {
        log.info("post {} is live", event.get("post_id"));
    }

    @EventListener
    void onFailed(FoPostDeliveryFailedEvent event) {
        log.warn("{} rejected it: {}", event.get("platform"), event.get("error"));
    }

    @EventListener
    void everything(FoPostWebhookEvent event) {
        log.debug("{} (delivery {})", event.getEvent(), event.getDeliveryId());
    }
}
EventClass
post.publishedFoPostPostPublishedEvent
post.failedFoPostPostFailedEvent
post.partially_failedFoPostPostPartiallyFailedEvent
delivery.publishedFoPostDeliveryPublishedEvent
delivery.failedFoPostDeliveryFailedEvent
delivery.delayedFoPostDeliveryDelayedEvent
account.health_changedFoPostAccountHealthChangedEvent
anything newerFoPostWebhookEvent

Listeners run synchronously on the request thread. An exception that escapes one becomes a 500 and FoPost retries the delivery, which is useful on purpose, but annotate the listener with @Async if you would rather acknowledge first. event.getDeliveryId() is unique per attempt, so keep your handler idempotent.

If your application uses Spring Security, permit the webhook path: FoPost signs its deliveries but does not carry a session or a bearer token.

Health

With Spring Boot Actuator on the classpath, /actuator/health gains a fopost entry that lists the workspaces the key can reach:

{ "status": "UP", "details": { "baseUrl": "https://api.fopost.com", "workspaces": 2 } }

A failure reports the API's status and error code. The key never appears in the response. Switch the entry off with management.health.fopost.enabled=false.

Next

Related documentation
  • SDKs & Integrations

    Official FoPost clients for TypeScript, Python, PHP, Ruby, Go, Rust, Java, .NET, Swift, Kotlin, Dart, and Elixir, framework integrations from Laravel to Next.js, and tooling for the CLI, CI, Terraform, and the automation platforms.

  • SDKs Overview

    Every official FoPost client, what it covers, and how to pick one.

  • TypeScript SDK

    The official TypeScript and Node.js client for the FoPost API.

  • Python SDK

    The official Python client for the FoPost API.

  • PHP SDK

    The official PHP client for the FoPost API, with no framework and no HTTP library.

  • Ruby SDK

    The official Ruby client for the FoPost API, with no runtime dependencies.

  • Go SDK

    The official Go client for the FoPost API.

  • Rust SDK

    The official Rust client for the FoPost API, async and built on reqwest.

Was this helpful?

On this page