
I'm back from my summer vacation with a quick and hopefully useful tip!
Whether you're using Nuxeo as an ECM or DAM in your organization, there's almost always a need to integrate with external systems.
Sometimes, those systems need to call a publicly accessible endpoint on your Nuxeo server-like to notify you when a job is done or to push data back into the platform.
Let me show you how easy it is to create such an endpoint using Nuxeo WebEngine with JAX-RS.
In this example, I was working on an integration with an external archiving system. We submit restore requests from Nuxeo, and when the restore is completed on their end, their system needs to call an open URL on the Nuxeo side to let us know that the job is finished.
The endpoint must support:
We want to add an open, unauthenticated endpoint that accepts a POST request like this:
POST http://localhost:8080/nuxeo/site/syncstatus/update
With the payload:
{
"jobId": "3da5bea3-4a09-3180-8c72-ad290b80f08c",
"eventClass": "JOB",
"status": "COMPLETE"
}
Overview of the Flow:
External System
│
▼
POST /site/syncstatus/update
│
▼
Nuxeo processes custom payload
Nuxeo supports JAX-RS via WebEngine, which is exactly what we'll use to expose this API: 📘 https://doc.nuxeo.com/nxdoc/webengine-jax-rs/
In your XML contribution, register the open URL:
<extension point="openUrl"
target="org.nuxeo.ecm.platform.ui.web.auth.service.PluggableAuthenticationService">
<openUrl name="syncstatus">
<grantPattern>${org.nuxeo.ecm.contextPath}/site/syncstatus</grantPattern>
</openUrl>
</extension>
Create a new class extending ModuleRoot, mapped to /syncstatus. 📘 Reference: ModuleRoot.java
@Path("/syncstatus")
@Produces("text/html;charset=UTF-8")
@WebObject(type = "syncstatus")
/**
* Open endpoint to receive callback
*/
public class SyncStatus extends ModuleRoot {
public static final Log log = LogFactory.getLog(SyncStatus.class);
@Context
private HttpServletRequest request;
@POST
@Path("update")
@Produces(MediaType.APPLICATION_JSON)
public Response syncJob(JobPayload request) {
return syncJob(request.getJobId(), request.getEventClass());
}
}
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class JobPayload {
private String jobId;
private String eventClass;
private String status;
public JobPayload() {}
public String getJobId() { return jobId; }
public void setJobId(String jobId) { this.jobId = jobId; }
public String getEventClass() { return eventClass; }
public void setEventClass(String eventClass) { this.eventClass = eventClass; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
}
@Provider
@Consumes(MediaType.APPLICATION_JSON)
public class JobPayloadReader implements MessageBodyReader<JobPayload> {
private static final ObjectMapper objectMapper = new ObjectMapper();
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return JobPayload.class.isAssignableFrom(type)
&& MediaType.APPLICATION_JSON_TYPE.isCompatible(mediaType);
}
@Override
public JobPayload readFrom(Class<JobPayload> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders,
InputStream entityStream) throws IOException {
return objectMapper.readValue(entityStream, JobPayload.class);
}
}
That's it! You now have an open Nuxeo endpoint that accepts POST requests with a custom JSON payload.
openUrl.curl -X POST http://localhost:8080/nuxeo/site/syncstatus/update \
-H "Content-Type: application/json" \
-d '{
"jobId": "3da5bea3-4a09-3180-8c72-ad290b80f08c",
"eventClass": "JOB",
"status": "COMPLETE"
}'
Let me know if you've built similar integrations or want to explore more advanced patterns like token auth or validation.
Keep reading
Yes, Nuxeo is still open source under Apache 2.0—and you can run it in production. Here’s exactly how, including the CLID requirement and how to build from source.
Read articleNuxeo external shares are convenient but anyone with the link can use them. Here’s how to protect those links with a passcode by extending TokenAuthenticator.
Read articleThe official Nuxeo roadmap from Hyland CommunityLIVE: what ships in H2 2025, what’s planned for H1 2026, and what’s coming in H2 2026 and beyond.
Read articleTell us what you're struggling with, and we'll tell you how we can help you.
Talk to us