Public
Likepwv-fund-application
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Viewing readonly version of main branch: v86View latest version
A secure Netlify webhook handler for processing fund application form submissions. This webhook receives form submissions from Netlify Forms, verifies their authenticity, stores the data, and sends notifications via email and Slack.
- ✅ Secure JWS Signature Verification - Validates webhook authenticity using HMAC-SHA256
- ✅ Data Storage - Stores submissions in Val Town blob storage with deduplication
- ✅ Email Notifications - Sends formatted emails to the fund team
- ✅ Slack Integration - Posts notifications to Slack channels
- ✅ Comprehensive Error Handling - Proper HTTP status codes and error responses
- ✅ Request Logging - Detailed logging for debugging and monitoring
The webhook implements robust security by verifying Netlify's JWS (JSON Web Signature) for every incoming request:
- Header Validation: Requires
x-netlify-eventandx-webhook-signatureheaders - HMAC Verification: Uses HMAC-SHA256 to verify the signature against the request body
- Secret Management: Uses environment variable
NETLIFY_FORM_JWSfor the signing secret
| Status Code | Condition | Response |
|---|---|---|
401 Unauthorized | Invalid or missing signature | {"ok": false, "error": "Invalid signature"} |
400 Bad Request | Missing headers or unknown event | {"ok": false} |
405 Method Not Allowed | Non-POST requests | "PWV Deal Webhook - Method not allowed" |
500 Internal Server Error | Missing environment variables | {"ok": false, "error": "Server configuration error"} |
# Netlify webhook signing secret (JWS) NETLIFY_FORM_JWS=your_netlify_jws_secret # Slack webhook URL for notifications SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
The webhook expects form submissions with the following fields:
name- Applicant's nameemail- Applicant's email address (required)company- Company namewebsite- Company website URLdeck- Link to pitch deckmessage- Additional message/notes
graph TD A[Netlify Form Submitted] --> B[Webhook Receives POST] B --> C[Verify Headers Present] C --> D[Verify JWS Signature] D --> E[Check Event Type] E --> F[Parse Form Data] F --> G[Validate Required Fields] G --> H[Check for Duplicates] H --> I[Store in Blob Storage] I --> J[Send Email Notification] J --> K[Send Slack Notification] K --> L[Return Success Response]
- Key Format:
pwv-fund-submission-{submission_id} - Storage: Val Town blob storage (JSON format)
- Deduplication: Prevents duplicate processing of the same submission
- Recipient:
dt@prestonwernerventures.com - Subject:
PWV Fund - New Submission - {company_name} - Format: Structured text with all form fields and extracted domain
- Channel: Configured via
SLACK_WEBHOOK_URL - Format: Formatted message with submission details and edit link
POST /
| Header | Required | Description |
|---|---|---|
x-netlify-event | Yes | Event type (must be "submission_created") |
x-webhook-signature | Yes | HMAC-SHA256 signature (format: "sha256=...") |
Content-Type | Yes | application/json |
{ "id": "submission_unique_id", "data": { "name": "John Doe", "email": "john@example.com", "company": "Example Corp", "website": "https://example.com", "deck": "https://deck-link.com", "message": "We're building the future..." } }
{ "ok": true }
{ "ok": true }
{ "ok": false, "error": "Invalid signature" }
The webhook can be tested using the Val Town fetch tool or any HTTP client:
curl -X POST https://your-webhook-url.web.val.run \ -H "Content-Type: application/json" \ -H "x-netlify-event: submission_created" \ -H "x-webhook-signature: sha256=valid_signature" \ -d '{"id":"test","data":{"name":"Test","email":"test@example.com","company":"Test Co","website":"https://test.com","deck":"","message":"Test submission"}}'
- Logs: All requests and errors are logged with detailed context
- Request History: Use Val Town's request history to debug issues
- Error Tracking: Comprehensive error messages for troubleshooting
- Set Environment Variables: Configure
NETLIFY_FORM_JWSandSLACK_WEBHOOK_URL - Deploy to Val Town: The webhook is automatically deployed as an HTTP endpoint
- Configure Netlify: Set the webhook URL in your Netlify form settings
- Test: Submit a test form to verify the integration
- Secret Rotation: Regularly rotate the
NETLIFY_FORM_JWSsecret - HTTPS Only: Webhook only accepts HTTPS requests
- Input Validation: All form data is validated before processing
- Error Handling: Sensitive information is not exposed in error messages
- 401 Unauthorized: Check that
NETLIFY_FORM_JWSmatches Netlify's webhook secret - Missing Headers: Ensure Netlify is configured to send the required headers
- 500 Errors: Verify all environment variables are set correctly
- Email/Slack Failures: Check respective service configurations and credentials
- Check Val Town request logs for detailed error information
- Verify webhook URL is correctly configured in Netlify
- Test with a minimal payload to isolate issues
- Ensure environment variables are properly set
This project is part of Preston-Werner Ventures' internal tooling.