Webhooks
FreeStuff's webhooks are POST
requests. Each request is refered to as a 'Message' below. The messages are delivered to the url you have configured on your dashboard. All data is in the shape of the compatibility date defined on the dashboard.
Message Payload
The message payload (http body) follows the Standard Webhooks Spec and looks as follows:
{
"type": "fsb:event:announcement_created",
"timestamp": "2022-11-03T20:26:10.344522Z",
"data": {
// ...
}
}
See Event List for a list of events.
Message Headers
The webhook request will have the following headers:
X-Compatibility-Date
- the compatibility date of the content send in the payload's data fieldWebhook-Id
- the message id, see verifying the requestWebhook-Timestamp
- the message send timestamp, see verifying the requestWebhook-Signature
- the message signature, see verifying the request
Verifying the request
FreeStuff signs every webhook request as per Standard Webhooks Spec. While not required, it is highly recommended you check for a valid signature before processing any events received.
- You can find your Ed25519 public key on your app page
- The content to be verified is
msg_id.timestamp.payload
with msg_id and timestamp being provided asWebhook-Id
andWebhook-Timestamp
headers respectively - Make sure to take the raw http body (prior to parsing the JSON content) for the verification
payload
- Make sure to store the
msg_id
for a certain amount of time to prevent package duplication and replay attacks - Make sure to ignore requests with an old
Webhook-Timestamp
value - Make sure to use the payload body
timestamp
field as the contextual timestamp and use the header only for verification
Resends
FreeStuff attempts to resend failed deliveries as per Standard Webhooks Spec. You are required to respond with a 2xx
status code after successfully receiving the data.
- Failure to process the data or perform actions with the data on your end should not yield a non-2xx status code as the message was delivered successfully
- While the Standard Webhooks Spec suggests a schedule for resends, FreeStuff may use a different timing for when resends are scheduled
- If you fail to receive multiple events in a row (no 2xx codes returned in multiple consecutive events spanning multiple days) your webhook will be considered dead and will be removed from our system. This will not revoke your api access entirely but you will have to configure your webhook again.
Responding to webhook requests
- A code of
204 No Content
with an empty body is prefered as the server will ignore your response body anyway - If for any reason you cannot send a
204
, any other2xx
code is accepted as well - You may send a
X-Set-Compatibility-Date
header with a compatibility date on your response- If the value is a valid compatibility date the setting in your app will be overwritten to use this compatibility date for all subsequent deliveries
- The new compatibility date already applies to resends so you can respond with a
4xx
code if you read an unexpectedX-Compatibility-Date
request header and force FreeStuff to deliver the message again with the correct date - Library authors are encouraged to set this header on every response to the newest compatibility date their library is compatible with, as well as to
4xx
every request with an incompatibleX-Compatibility-Date
request header. This way users can easily install and update your library without manual configuration on the dashboard or even knowing about the compatibility date system - If you respond with a non
2xx
status while having an invalid value for yourX-Set-Compatibility-Date
, the message will not be scheduled for a resend as it is assumed you let the request fail because of the compatibility date missmatch while expecting a non-valid date
- You may send a
X-Client-Library
header with details about your library- Library authors are encouraged to set this header on every response
- The format should be
Library Name/version (url to library homepage or git repo)
- e.g.FreeStuff.py/1.0.2 (https://github.com/my/fake-repo)
Event List
fsb:event:ping
Fired either when the ping button was pressed on your dashboard or periodically to check if your webhook is still operational.
The data
field will contain the following object:
{
"manual": boolean // will be true if you manually requested this ping, false otherwise
}
fsb:event:announcement_created
Fired when a new announcement is published.
The data
field will contain a single ResolvedAnnouncement
. Check it's resolvedProducts
field for a list of all new products.
fsb:event:product_updated
Fired when a previously published product is updated.
The data
field will contain the full Product
data, not just the changes.
2025-03-01
. Newer versions might differ in details.