Posting this for my future self.
I recently needed to define an HTTP POST endpoint that accepted a json payload.
I defined a service endpoint in zcml like this:
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:plone="http://namespaces.plone.org/plone">
<adapter factory=".post.ImportData" name="import_data"/>
<plone:service
method="POST"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
factory=".post.ImportDataPost"
name="@import_data"
permission="zope2.View"
/>
</configure>
one key concept, is that the data is passed as a json string in the body. Which is retrieved like this:
data = self.request['BODY'])
myjson = json.loads(data)
I found this documentation helpful:
https://docs.plone.org/develop/plone/serving/http_request_and_response.html#request-body