Skip to main content
Flatpeak sends each event to your endpoint as a POST request. Register an endpoint and choose its events in Console > Webhooks.

Delivery

Return 200 within 10 seconds; any other response is a failure. Respond first, then do slow work. Flatpeak retries a failed delivery after 30 seconds, 1 hour, 6 hours, 12 hours and 24 hours, each counted from the previous attempt. After the last retry, resend it from Console > Webhooks > Logs.

Verify signatures

Flatpeak signs every delivery, so verify the signature before you act on the event. The signed message is {Flatpeak-Timestamp}.{raw request body}. The algorithm is RSA-PSS with SHA-256 (PS256): RSA-2048 key, MGF1-SHA256, salt length 32 bytes. Live and test mode use separate keys.
  1. Read the raw request body bytes before any JSON parsing.
  2. Build the message: the timestamp, a literal ., then the raw body.
  3. Fetch the JWKS and pick the key whose kid equals Flatpeak-Key-ID. Cache it, and refetch on an unknown kid, because keys rotate.
  4. Strip v1=, base64url-decode the signature, and verify it with RSA-PSS SHA-256.
  5. Reject a timestamp more than 5 minutes from your clock.
Fetch the JWKS:
Raw body: express.raw({ type: 'application/json' }) (Express), a raw contentTypeParser (Fastify), request.get_data() (Flask), await request.body() (FastAPI), request.body (Django), io.ReadAll(r.Body) (Go).
Reproduce the check with OpenSSL. Save the raw body as raw_body.json and the JWKS as jwks.json. Copy the header values from Console > Webhooks > Logs.
Verified OK means success. On Verification failure, check the body bytes, the key ID and the signature decode.