Skip to main content

REST API

The MES exposes two APIs: the partner API (used by business partners through a B2B gateway) and the internal API (used by internal applications). Both are fully backwards-compatible with the B2B Hub API. A running instance serves the OpenAPI specifications via springdoc, grouped per API version (Swagger UI at /swagger-ui.html, OpenAPI JSON at /v3/api-docs/{group}).

APIBase pathStatus
Partner V4/api/partner/v4/messagesCurrent
Partner V3/api/partner/v3/messagesDeprecated since 4.0.0, for removal
Internal V3/api/internal/v3/messagesCurrent

Message payloads are streamed in the request/response body as-is. mes-metadata carries a Base64-encoded JSON object of string key/value pairs (validated against schema/mes-metadata-schema.json); it is accepted on the internal publish operation and returned on the partner V4 download and next-message operations.

Partner V4

Content-Type / Accept headers are mandatory, media types are configurable (see Media types and size limit).

OperationMethod and path
Upload a messagePUT /api/partner/v4/messages/{messageId}
Poll for new messagesGET /api/partner/v4/messages
Download a messageGET /api/partner/v4/messages/{messageId}
Get next messageGET /api/partner/v4/messages/{lastMessageId}/next

Request headers and query parameters:

NameKindOperationsRequiredDescription
bp-idHeaderallyesBusiness partner identification; the token must hold the partner roles for this bpId
message-typeHeaderuploadyesBusiness type of the message body
Content-TypeHeaderuploadyesMedia type of the payload; must be one of the configured media types
AcceptHeaderdownloadyesExpected media type; must match the stored content type of the message
partner-topicHeaderuploadnoPartner topic stored with the message
partner-external-referenceHeaderuploadnoPartner-defined external reference stored with the message
topicNameQuerypoll, nextnoReturn only messages published into the given topic
groupIdQuerypollnoReturn only messages with the given group ID
lastMessageIdQuerypollnoPolling cursor — return only messages published after this message
partnerTopicQuerypoll, nextnoReturn only messages with the given partner topic
partnerExternalReferenceQuerypoll, nextnoReturn only messages with the given partner external reference
sizeQuerypollnoMaximum number of messages returned (default 1000)

Response headers on download and next-message:

NamePresentDescription
message-idalwaysmessageId of the returned message
partner-topicwhen setPartner topic of the message
partner-external-referencewhen setPartner-defined external reference of the message
mes-metadatawhen setBase64-encoded JSON metadata of the message

Example: upload a message (inbound)

PUT /api/partner/v4/messages/cc7d5097-4d3f-4fff-af91-fd3680199642 HTTP/1.1
Authorization: Bearer <token issued by the B2B gateway>
bp-id: 123
message-type: InvoiceMessage
partner-topic: invoices
Content-Type: application/xml

<invoice>...</invoice>
HTTP/1.1 201 Created

Re-sending the identical payload for the same messageId is an idempotent no-op (201); a different payload for the same messageId is rejected with 409 Conflict.

Example: poll for new messages (outbound)

lastMessageId is the polling cursor — pass the last messageId already processed, omit it to start from the beginning of the retention window:

GET /api/partner/v4/messages?topicName=orders&lastMessageId=7f3f6e0a-1b2c-4d5e-8f90-123456789abc&size=100 HTTP/1.1
Authorization: Bearer <token issued by the B2B gateway>
bp-id: 123
HTTP/1.1 200 OK
Content-Type: application/json

{
"messages": [
{
"messageId": "9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d",
"messageType": "OrderResponseMessage",
"groupId": "batch-7",
"partnerTopic": "orders",
"contentType": "application/xml",
"partnerExternalReference": "ref-4711",
"metadata": { "orderId": "4711" }
}
]
}

Empty fields are omitted from the JSON response.

Example: download a message (outbound)

GET /api/partner/v4/messages/9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d HTTP/1.1
Authorization: Bearer <token issued by the B2B gateway>
bp-id: 123
Accept: application/xml
HTTP/1.1 200 OK
message-id: 9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d
partner-topic: orders
partner-external-reference: ref-4711
mes-metadata: eyJvcmRlcklkIjoiNDcxMSJ9
Content-Length: 987

<orderResponse>...</orderResponse>

GET /api/partner/v4/messages/{lastMessageId}/next behaves like the download but returns the next message published after lastMessageId (or 404 if there is none).

Partner V3 (deprecated)

Deprecated since 4.0.0 and planned for removal — use Partner V4. The operations mirror the V4 API, but only application/xml is supported (regardless of the configured media types), there is no partner-external-reference / metadata support, and the download returns the payload without response headers (next-message returns only message-id).

OperationMethod and path
Upload a message (XML)PUT /api/partner/v3/messages/{messageId}
Poll for new messages (XML)GET /api/partner/v3/messages
Download a message (XML)GET /api/partner/v3/messages/{messageId}
Get next message (XML)GET /api/partner/v3/messages/{lastMessageId}/next

Request headers and query parameters:

NameKindOperationsRequiredDescription
bp-idHeaderallyesBusiness partner identification; the token must hold the partner roles for this bpId
message-typeHeaderuploadyesBusiness type of the message body
topicNameQuerypoll, nextnoReturn only messages published into the given topic
groupIdQuerypollnoReturn only messages with the given group ID
lastMessageIdQuerypollnoPolling cursor — return only messages published after this message
partnerTopicQuerypoll, nextnoReturn only messages with the given partner topic
sizeQuerypollnoMaximum number of messages returned (default 1000)

The poll returns the message list as XML (<messages><message>...</message></messages>, without contentType, partnerExternalReference and metadata).

Internal V3

Content-Type / Accept headers are mandatory, media types are configurable (see Media types and size limit).

OperationMethod and path
Publish a message to a partnerPUT /api/internal/v3/messages/{messageId}?topicName=...
Download an inbound partner messageGET /api/internal/v3/messages/{messageId}

Request headers and query parameters:

NameKindOperationsRequiredDescription
bp-idHeaderpublishyesIdentification of the receiving business partner
message-typeHeaderpublishyesBusiness type of the message body
Content-TypeHeaderpublishyesMedia type of the payload; must be one of the configured media types
AcceptHeaderdownloadyesExpected media type; must match the stored content type of the message
partner-topicHeaderpublishnoPartner topic stored with the message
partner-external-referenceHeaderpublishnoPartner-defined external reference stored with the message
mes-metadataHeaderpublishnoBase64-encoded JSON object of string key/value pairs, returned to the partner on download
topicNameQuerypublishyesTopic to publish the message into
groupIdQuerypublishnoGrouping identifier to group multiple messages

Example: publish a message to a partner (outbound)

PUT /api/internal/v3/messages/7f3f6e0a-1b2c-4d5e-8f90-123456789abc?topicName=orders&groupId=batch-7 HTTP/1.1
Authorization: Bearer <token issued by the system's Keycloak>
bp-id: 123
message-type: OrderResponseMessage
partner-topic: orders
partner-external-reference: ref-4711
mes-metadata: eyJvcmRlcklkIjoiNDcxMSJ9
Content-Type: application/xml

<orderResponse>...</orderResponse>
HTTP/1.1 201 Created

Example: download an inbound partner message

Typically after receiving the B2BMessageReceivedEvent on Kafka:

GET /api/internal/v3/messages/cc7d5097-4d3f-4fff-af91-fd3680199642 HTTP/1.1
Authorization: Bearer <token issued by the system's Keycloak>
Accept: application/xml
HTTP/1.1 200 OK
Content-Length: 1234

<invoice>...</invoice>

Returns 403 if the message is blocked by the malware scan status (see Malware Scanning).

Media types and size limit

Uploaded payloads must match one of the configured media types (jeap.messageexchange.api.media-types, default application/xml); the partner V3 API accepts only application/xml regardless of this configuration. On download, the Accept header must match the stored content type. Requests with a body larger than jeap.messageexchange.api.max-request-body-size-in-bytes (default 200 MB) are rejected.

Backwards compatibility quirks

For compatibility with B2B Hub clients, trailing slashes in resource paths are removed automatically.

Notable status codes

StatusMeaning
201 CreatedMessage stored (uploading identical content for an existing messageId is an idempotent no-op)
400 Bad RequestInvalid mes-metadata header (not Base64, not valid JSON, or schema violation), or invalid XML on the partner V3 upload
403 ForbiddenToken not authorized for the bp-id header, or inbound download blocked by the malware scan status (see Malware Scanning)
404 Not FoundUnknown message, or the payload has expired (see Operations)
406 Not AcceptableContent-Type/Accept does not match the configured media types or the stored content type
409 ConflictUpload reusing an existing messageId with different content

Authorization

Requests are authorized with jEAP semantic roles on two resources: b2b-message-in (partner to application) and b2b-message-out (application to partner). <system> is the configured jeap.security.oauth2.resourceserver.system-name.

Partner API — tokens issued by the B2B gateway's Keycloak, roles are business-partner roles (valid only for the partner's own bpId):

VerbResourceRole
PUTIncoming message<system>_@b2bmessagein_#write
GETOutgoing message<system>_@b2bmessageout_#read

Internal API — tokens issued by the system's Keycloak, roles are user roles (valid for any bpId):

VerbResourceRole
PUTOutgoing message<system>_@b2bmessageout_#write
GETIncoming message<system>_@b2bmessagein_#read

Example role claims:

// internal application (user roles)
"userroles": [
"wvs_@b2bmessageout_#write",
"wvs_@b2bmessagein_#read"
]

// business partner 123 (partner API, token issued by the B2B gateway's Keycloak)
"bproles": {
"123": [
"wvs_@b2bmessagein_#write",
"wvs_@b2bmessageout_#read"
]
}

See Getting Started for systems acting on behalf of multiple business partners.