Fuik
A fish trap for webhooks
Fuik (Dutch for fish trap) is a Rails engine that catches and stores webhooks from any provider. View all events in the admin interface, then create event classes to add your business logic.
Sponsored By Rails Designer
Quick start
# Install
bundle add fuik
bin/rails generate fuik:install
bin/rails db:migrate
# Point your webhook to
POST https://yourdomain.com/webhooks/stripeThat's it. Webhooks are captured and visible at /webhooks.
Installation
Add to your Gemfile:
gem "fuik"Then run:
bundle install
bin/rails generate fuik:install
bin/rails db:migrateThe 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.
Add business logic
Generate event handlers when you're ready to automate:
bin/rails generate fuik:provider stripe checkout_session_completed customer_subscription_updatedThis 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
endImplement 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
endIf 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_idAdd 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.
Contributing
This project uses Standard for formatting Ruby code. Please make sure to run rake before submitting pull requests.
License
The gem is available as open source under the terms of the MIT License.
