Webhooks
Webhooks allow you to receive real-time updates from our servers. They enable you to build custom logic on your server based on events that happen during the app release process.
Getting Started
To get started, you need to create a webhook. You can do this by going to the settings page and clicking on the "Create Webhook" button.
You will be asked to provide
- Webhook URL - The URL that will receive the webhook events
- Webhook Secret - A secret that will be used to verify the webhook events
- Webhook Description - A description for your webhook
How to generate a secret key
The secret key is a unique string that is used to verify the webhook events. You can generate a secret key using the following command:
# Generate a random string
openssl rand -base64 16
We only store the encrypted secret key on our servers. This means that you will not be able to retrieve the secret key once you have created the webhook. So make sure to save it in your vault.
Once you create the webhook, you have the ability to enable or disable the webhook.
Webhook Events
Webhook events are sent to your webhook URL as a POST request with payload which contains the event information and headers which contain information to verify and prevent replay attacks.
Supported Events
Event | Description |
---|---|
ios.appstore.review.started | Triggered when a new iOS app submission review is started. |
ios.appstore.review.completed | Triggered when a new iOS app submission review is completed. |
If you need us to support additional events, please contact us.
Payload
The request body for the ios.appstore.review.started
event will contain the following information:
Field | Description |
---|---|
event | The event type that was triggered |
buildId | The build ID of the app submission |
cfBundleIdentifier | The bundle identifier |
cfBundleVersion | The bundle version |
cfBundleShortVersionString | The bundle short version string |
submittedAt | The date and time that the build was submitted |
{
"event": "ios.appstore.review.started",
"buildId": "17127a98-0989-46a8-a69a-b3a6378f653d",
"cfBundleIdentifier": "app.wolfia",
"cfBundleVersion": "1",
"cfBundleShortVersionString": "1.0.0",
"submittedAt": "2023-02-22T17:19:25.503847Z"
}
The request body for the ios.appstore.review.completed
event will contain the following information:
Field | Description |
---|---|
event | The event type that was triggered |
buildId | The build ID of the app submission |
cfBundleIdentifier | The bundle identifier |
cfBundleVersion | The bundle version |
cfBundleShortVersionString | The bundle short version string |
completedAt | The date and time that the build was completed |
{
"event": "ios.appstore.review.started",
"buildId": "17127a98-0989-46a8-a69a-b3a6378f653d",
"cfBundleIdentifier": "app.wolfia",
"cfBundleVersion": "1",
"cfBundleShortVersionString": "1.0.0",
"completedAt": "2023-02-23T17:19:25.503847Z"
}
Headers
The header of the request will contain the following information:
Header | Description |
---|---|
X-Wolfia-Signature | The signature of the request body signed with the webhook secret using the HMAC-SHA256 algorithm. This can be used to verify the request. (Recommended) |
X-Wolfia-Until | The date and time until the webhook request should be accepted. This helps prevent replay attacks. |
X-Wolfia-Idempotency-Key | The idempotency key of the request. This can be used ensure that you only receive the request once. (Optional) |
Consuming Webhook Events
This section walks you through the steps to process a webhook event on your server. You can use the following code snippets as a starting point.
Verify and prevent replay attacks
To verify that the webhook event was sent by Wolfia, you can use the X-Wolfia-Signature
header. This header contains the signature of the request body. You can use this signature to verify that the request body was not modified.
To verify the signature, you need to use the webhook secret that you provided when you created the webhook. You can use your webhook secret to generate a signature using the HMAC-SHA256 algorithm.
var crypto = require('crypto');
// Prevents man-in-the-middle attacks by verifying the signature
function isWebhookVerified(req) {
const body = req.body;
const validUntil = req.header("X-Wolfia-Until");
const signature = req.header("X-Wolfia-Signature");
return verifySignature(body, validUntil, signature);
}
// Prevents replay attacks by verifying the expiration date
function isWebhookExpired(req) {
const validUntil = req.header("X-Wolfia-Until");
const validDateTime = new Date(validUntil * 1000);
const currentTime = new Date();
return validDateTime < currentTime;
}
function verifySignature(body, validUntil, signature) {
const secret = "secret you entered when creating the webhook goes here"
const data = JSON.stringify(body) + "." + validUntil;
const hash = crypto.createHmac('sha256', secret).update(data).digest('hex');
return hash === signature
}
Handle the webhook event
Once you have verified the webhook event, you can process the event. You can use the event
field to determine what type of event was triggered.
var express = require('express');
var router = express.Router();
router.post('/', function (req, res, next) {
const isExpired = isWebhookExpired(req);
const isVerified = isWebhookVerified(req);
if (isVerified && !isExpired) {
processWebhook(req.body);
res.status(200).send('OK');
} else if (isVerified && isExpired) {
res.status(400).send("Webhook expired");
} else if (!isVerified) {
res.status(400).send("Invalid signature");
} else {
res.status(400).send("Unknown error");
}
});
function processWebhook(body) {
switch (body.event) {
case "ios.appstore.review.started":
console.log(`Started review for version: ${body.cfBundleShortVersionString}.${body.cfBundleVersion}`)
// handle review start
break;
case "ios.appstore.review.completed":
console.log(`Completed review for version: ${body.cfBundleShortVersionString}.${body.cfBundleVersion}`)
// handle review complete
break;
default:
console.log("Unknown event: " + body.event)
}
}
Acknowledging Webhook Events
Once you have processed the webhook event, you should acknowledge the event by sending a 200 response. This will prevent the event from being sent again.
If you do not acknowledge the event, the event will be sent again for up to 10 times. After 10 times, the event will be discarded.
Testing Webhook Events
Once you have created a webhook, you can test it by sending a test event. If you head on over to the settings page, you can see the Debug
button. Clicking on this button will open the dialog below.
You can use the dialog to send a test event to your webhook. You can select the event type and once you are ready, click on the Send test webhook
button.
And that's it! ✅ You are now ready to start receiving webhook events from Wolfia. If you have any questions, please feel free to reach out to us.