Webhooks
To be notified when sites are ready, you can register a webhook URL for your organization via your organization options panel in the Chloris Platform web interface.
You will be asked to provide an HTTPS publicly-accessible URL for the webhook and a signing secret (a random string of your choosing).
This URL will be called when the site is ready. The webhook will be called with a POST request with the following JSON body:
{
type: "reportingUnit",
data: {
organizationId: "your-organization-id",
reportingUnitId: "your-reporting-unit-id",
analysisCompletedAt: "2024-01-01T00:00:00.000Z",
// ISO 8601
exportCompletedAt: "2024-01-01T00:00:00.000Z",
// ISO 8601, omitted if geospatial outputs are not yet available
},
}
If the request fails, the webhook will be retried once after a random delay of 10-30 seconds. If the request fails again, the webhook will not be retried. In the future, we may add further retry logic, so please let us know if you have a specific use case that requires this.
The analysisCompletedAt timestamp is included to help you determine if the analysis results have been updated since the last time you checked. In the event that a site is reprocessed, the analysisCompletedAt timestamp will be updated. This can happen if the site is reprocessed due to a bug fix or as new data becomes available. If your system is caching the results of the site, you can use this timestamp to determine if you need to update your cache.
If you have licensed geospatial outputs, the webhook will also be invoked a second time with an additional
As of 1.5.0 exportCompletedAt timestamp in the payload. This timestamp indicates when the geospatial outputs are ready to be downloaded. If you are using the webhook to download the geospatial outputs, you can use this timestamp to determine when to download the outputs.exportCompletedAt is deprecated and will be removed in a future version. Downloads are now always available when the webhook is called. For backwards compatibility, the field will continue to be included in webhook calls using the same value as analysisCompletedAt, but will be removed in a future version.
Control sites (or any site marked hidden: true) will not trigger a webhook, but will delay the primary site's webhook notification until the control site is ready.
Because there are several scenarios where the webhook will be called multiple times, you should ensure that your webhook endpoint is idempotent. This means that if the webhook is called multiple times, the final state of the site in your system will be both valid and up to date.
Signature validation
When our system calls your webhook endpoint, we will include a signature in the X-Signature http header. We recommend that you verify this signature to ensure that the request is actually from us.
The X-Signature header is a hash made up of the signing secret you specified when creating the
webhook in your Chloris Platform account plus the request body. To verify each request to your webhook, you should re-create the hash and compare it to the signature in the header.
Here is an example of validating the signature in Node / Javascript:
import crypto from "crypto";
// the signing secret you specified when creating the webhook
const secret = "";
const body = ""; // the raw request body
const hmac = crypto.createHmac("sha256", secret);
const digest = Buffer.from(hmac.update(request.rawBody).digest("hex"), "utf8");
const signature = Buffer.from(request.get("X-Signature") || "", "utf8");
if (!crypto.timingSafeEqual(digest, signature)) {
throw new Error("Invalid signature.");
}
And here is an example of validating the signature in Python:
import hmac
import hashlib
# the signing secret you specified when creating the webhook
secret = ''
# the signature in the X-Signature header
signature = ''
# the raw request body (depending on your http library, you may need to encode this.)
body = ''
digest = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(digest, signature):
raise Exception('Invalid signature.')
Testing your webhook endpoint
Here is a curl command that will simulate a webhook call with the signing secret "secret1234" so you can test your endpoint:
curl -X POST \
-H "Content-Type: application/json" \
-H "X-Signature: 211eee254e5bab5761e82452a9cf37e1396329cadc9957a99ea64197bd1c25a0" \
-d '{"type": "reportingUnit", "data": {"organizationId": "your-organization-id", "reportingUnitId": "your-reporting-unit-id", "analysisCompletedAt": "2024-01-01T00:00:00.000Z"}}' \
http://localhost:8080/webhook