Fuik
Rails engine that catches and stores webhooks from any provider
Installation
Add to your Gemfile:
gem "fuik"
Then run:
bundle install
bin/rails generate fuik:install
bin/rails db:migrate
The engine mounts at /webhooks automatically.
Usage
View events
Visit /webhooks to see all received webhooks. Click any event to see the full payload, headers and status.
⚠️ The /webhooks path is by default not protected. Easiest is to set Fuik::Engine.config.events_controller_parent to a controller that requires authentication.
Add business logic
Generate event handlers when you’re ready to automate:
bin/rails generate fuik:provider stripe checkout_session_completed customer_subscription_updated
This creates:
app/webhooks/stripe/base.rbapp/webhooks/stripe/checkout_session_completed.rbapp/webhooks/stripe/customer_subscription_updated.rb
Each class is a thin wrapper around your business logic:
module Stripe
class CheckoutSessionCompleted < Base
def process!
User.find_by(id: payload.dig("client_reference_id")).tap do |user|
user.activate_subscription!
user.send_welcome_email
# etc.
end
@webhook_event.processed!
end
end
end
Implement Base.verify! to enable signature verification:
module Stripe
class Base < Fuik::Event
def self.verify!(request)
secret = Rails.application.credentials.dig(:stripe, :signing_secret)
signature = request.headers["Stripe-Signature"]
Stripe::Webhook.construct_event(
request.raw_post,
signature,
secret
)
rescue Stripe::SignatureVerificationError => error
raise Fuik::InvalidSignature, error.message
end
end
end
If Provider::Base.verify! exists, Fuik calls it automatically. Invalid signatures return 401 without storing the webhook.
Pre-packaged providers
Fuik includes ready-to-use templates for common providers.
Event type & ID lookup
Fuik automatically extracts event types and IDs from common locations:
Event Type:
- provider config (if exists);
- common headers (
X-Github-Event,X-Event-Type, etc.); - payload (
type,event,event_type); - falls back to
"unknown".
Event ID:
- provider config (if exists);
- common headers (
X-GitHub-Delivery,X-Event-Id, etc.); - payload (
id). - falls back to MD5 hash of request body.
Custom lookup via config
Create app/webhooks/provider_name/config.yml:
event_type:
source: header
key: X-Custom-Event
event_id:
source: payload
key: custom_id
Add your custom provider
Have a provider template others could use? Add it to lib/generators/fuik/provider/templates/your_provider/ and submit a PR!
Include:
-
base.rb.ttwith signature verification (if applicable); - event class templates with helpful TODO comments.