Skip to content

Handle external callbacks

Handle a provider’s status callback and complete the operation waiting for it. This example accepts POST /provider/status with an operation ID and status, using a shared bearer token.

public record ProviderStatus(String operationId, String status) {}
public record OperationCompleted(String operationId) {}
public class ProviderCallbacks {
@HandlePost("/provider/status")
WebResponse handle(ProviderStatus body, @HeaderParam("Authorization") String authorization) {
String expected = "Bearer " + ApplicationProperties.requireProperty("provider.callback.token");
if (!expected.equals(authorization)) {
return WebResponse.builder().status(401).build();
}
if ("completed".equals(body.status())) {
Fluxzero.publishEvent(new OperationCompleted(body.operationId()));
}
return WebResponse.builder().status(204).build();
}
}

Configure provider.callback.token through application properties (PROVIDER_CALLBACK_TOKEN in the environment). Register ProviderCallbacks as a handler. @HeaderParam supplies the header; a missing or incorrect token gets HTTP 401.

Store OperationStarted before calling the provider, using an operation ID your application already knows. The stateful handler waits for that ID’s completion:

public record OperationStarted(String operationId) {}
public record OperationFinished(String operationId) {}
@Stateful
public record AwaitingCallback(@EntityId @Association String operationId) {
@HandleEvent
static AwaitingCallback start(OperationStarted event) {
return new AwaitingCallback(event.operationId());
}
@HandleEvent
AwaitingCallback complete(OperationCompleted event) {
Fluxzero.publishEvent(new OperationFinished(operationId));
return null;
}
}

Register AwaitingCallback.class (AwaitingCallback::class.java in Kotlin). @Association finds the waiting instance; returning null deletes it. Once that deletion is stored, another callback has no waiting instance to complete.

var callback = WebRequest.post("/provider/status")
.header("Authorization", "Bearer test-token")
.body(new ProviderStatus("op-1", "completed")).build();
TestFixture.create(new ProviderCallbacks(), AwaitingCallback.class)
.withProperty("provider.callback.token", "test-token")
.givenEvents(new OperationStarted("op-1"))
.whenWebRequest(callback)
.expectEvents(new OperationFinished("op-1"))
.andThen()
.whenWebRequest(callback)
.expectNoEventsLike(OperationFinished.class);

Use HTTPS. For a provider that signs callbacks, follow its signature protocol instead of this bearer-token example. See stateful handlers for persistence and retry behavior, and API integrations for the outgoing call.


© 2026 Fluxzero