Private add-on: converted Simple Function won't route to a Self-Hosted callback, a new one does

We have a private add-on running as a Simple Function. The documented limits,
15 seconds and 128 MB, are now the binding constraint: the add-on renders test
certificates as a PDF, and a job with 72 completed forms takes 10.9 seconds to
draw and 13.9 seconds end to end. A job with 98 forms uses 12.8 of the 15. The
same work on a Lambda we host ourselves at 1769 MB takes 1.5 seconds.

So we tried to move it, and hit three things we could not resolve from the
documentation.

  1. The Callback URL field will not take a Lambda ARN.

Setting Addon Type to “Self-Hosted Web Service Function” and pasting an ARN for
a function in our own AWS account gives “Not Ready (Invalid Callback URL)”. We
had expected this to work, because that same field holds an ARN when the add-on
is a Simple Function: it shows one pointing at ExternalSDK-SimpleFunction- in a ServiceM8 owned AWS account, with an alias per deployment.

Is there a supported way to configure an “AWS Lambda Function Add-on” as
described under Add-on Types, for a private add-on? The Addon Type dropdown
offers only External Integration, Self-Hosted Web Service Function, and Simple
Function (NodeJS). If it is supported, which AWS principal does ServiceM8 invoke
from, so we can write the resource-based policy?

  1. A Lambda Function URL works, but only on a newly created add-on.

Giving the same Lambda a Function URL and putting that HTTPS URL in the Callback
URL box works correctly on an add-on we created fresh for testing. ServiceM8
POSTs the JWT, we verify the HS256 signature with the App Secret, return
{“eventResponse”: “…”} and the modal renders it. 72 certificates came
back in 2.4 seconds.

Putting the identical configuration on our existing add-on, the one that has been
a Simple Function since 14 September, does not work. Status reports Ready, the
buttons appear, and every press returns:

“ServiceM8 is not authorized to invoke your addon Lambda function. Please
review Addon SDK Documentation regarding granting ServiceM8 access to invoke
your function and try again.”

Our CloudWatch logs show no request arriving at all, so ServiceM8 is not calling
the URL. It appears still to be attempting a Lambda invoke. We verified the three
fields directly in the form: addon_type is web-service-integration,
addon_callback_url is the https://.lambda-url..on.aws/ address, and
activation_url is set. Toggling it to an invalid value and back did not change
the behaviour.

Is there residual state on an add-on converted from a Simple Function that has to
be cleared, or is creating a new add-on the only path?

  1. Two smaller things that cost us time, in case they are worth a doc note.

Deploying a bundle to an add-on that is configured as a web service silently
resets Addon Type to Simple Function and overwrites the Callback URL with
ServiceM8’s own ARN. The Activation URL survives, so the settings page afterwards
looks partly changed rather than reset.

The Web Service Hosted Add-ons page says the output “will be rendered into the
ServiceM8 UI inside an iframe”, which reads as though it wants HTML. Returning
HTML gives “Invalid JSON Response Received”. It wants the same envelope a Lambda
returns, {“eventResponse”: “…”}. Worth saying explicitly on that page.

Related support request: #340637.

Hi Armin,

We’ve investigated this alongside ticket #340637.

Changing an existing add-on’s callback URL can currently take up to four hours to take effect. During that time, ServiceM8 may continue calling the previous endpoint even though the new URL is saved and the status shows Ready. This explains the difference you observed between the existing add-on and a newly created one.

You don’t need to recreate the add-on. Save the HTTPS callback and allow up to four hours before retesting, without deploying another Simple Function bundle during that period. We’ve also prepared a fix for this delay.

Regarding your other questions:

  • Lambda ARN: Self-Hosted Web Service Function expects an HTTPS URL. The separate direct AWS Lambda option is a legacy option available to developer accounts created before 10 February 2020. For your account, the Lambda Function URL approach is the supported route. The Add-on Types documentation needs to make this distinction clearer.
  • Bundle deployment: Deploying a Simple Function bundle changes the add-on back to ServiceM8 hosting and replaces its callback. Once you switch to self-hosting, deploy your function updates through your own hosting workflow.
  • Response format: You’re correct—the callback must return JSON containing eventResponse, for example {"eventResponse":"<html>...</html>"}. Returning bare HTML produces the error you saw.

One additional migration detail: HTTPS callbacks have a five-second response timeout and need their own OAuth flow; they don’t receive the temporary access token supplied to Simple Functions.

Thanks for documenting the comparisons and documentation gaps so clearly.

Cody

Hi Armin,

For the path you’re moving to, use Self-Hosted Web Service Function with an HTTPS callback URL, not a Lambda ARN. ServiceM8’s web-service hosted add-ons call the callback URL by HTTPS POST, and the event payload is sent as a JWT signed with the add-on’s App Secret.

The Lambda ARN you see on a Simple Function is part of ServiceM8-managed infrastructure, where ServiceM8 manages the server infrastructure and invokes the function for add-on events. The direct AWS Lambda Function Add-on model referenced in the docs isn’t available in the add-on type options you listed, and support-confirmed guidance is that Self-Hosted Web Service Function uses an HTTPS endpoint rather than a direct Lambda ARN.

For the converted add-on, the fact that the same HTTPS Function URL works on a newly created add-on, but the existing add-on still returns a Lambda invoke authorisation error and doesn’t hit your endpoint, needs us to check the add-on routing/configuration internally. That isn’t something we can safely diagnose from the public forum, so the best next step is to continue that part through the existing support request rather than changing Lambda policy or code.

On the response format, yes, we agree this should be clearer in the docs. For a Self-Hosted/Web Service callback, return HTTP 200 with Content-Type: application/json, and wrap the HTML in an eventResponse value, for example {“eventResponse”:“…”}.

We’ve also noted the feedback about bundle deployment changing the add-on type/callback settings, as that behaviour isn’t covered in the public docs we can point to here.

Thanks,
Cody