• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
pwv

pwv

pwv-fund-application

Handles PWV Fund form web hook
Public
Like
pwv-fund-application
Home
Code
3
README.md
H
main.ts
test-webhook.ts
Connections
Environment variables
3
Branches
2
Pull requests
Remixes
2
History
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.
Sign up now
Code
/
README.md
Code
/
README.md
Search
12/22/2025
Viewing readonly version of main branch: v92
View latest version
README.md

PWV Fund Application Webhook

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.

Features

  • ✅ 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

Security

Webhook Signature Verification

The webhook implements robust security by verifying Netlify's JWS (JSON Web Signature) for every incoming request:

  1. Header Validation: Requires x-netlify-event and x-webhook-signature headers
  2. HMAC Verification: Uses HMAC-SHA256 to verify the signature against the request body
  3. Secret Management: Uses environment variable NETLIFY_FORM_JWS for the signing secret

Error Responses

Status CodeConditionResponse
401 UnauthorizedInvalid or missing signature{"ok": false, "error": "Invalid signature"}
400 Bad RequestMissing headers or unknown event{"ok": false}
405 Method Not AllowedNon-POST requests"PWV Deal Webhook - Method not allowed"
500 Internal Server ErrorMissing environment variables{"ok": false, "error": "Server configuration error"}

Configuration

Required Environment Variables

# 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/...

Netlify Form Setup

The webhook expects form submissions with the following fields:

  • name - Applicant's name
  • email - Applicant's email address (required)
  • company - Company name
  • website - Company website URL
  • deck - Link to pitch deck
  • message - Additional message/notes

Workflow

1. Form Submission Processing

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]

2. Data Storage

  • Key Format: pwv-fund-submission-{submission_id}
  • Storage: Val Town blob storage (JSON format)
  • Deduplication: Prevents duplicate processing of the same submission

3. Notifications

Email Notification

  • Recipient: dt@prestonwernerventures.com
  • Subject: PWV Fund - New Submission - {company_name}
  • Format: Structured text with all form fields and extracted domain

Slack Notification

  • Channel: Configured via SLACK_WEBHOOK_URL
  • Format: Formatted message with submission details and edit link

API Reference

Endpoint

POST /

Headers

HeaderRequiredDescription
x-netlify-eventYesEvent type (must be "submission_created")
x-webhook-signatureYesHMAC-SHA256 signature (format: "sha256=...")
Content-TypeYesapplication/json

Request Body

{ "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..." } }

Response Examples

Success

{ "ok": true }

Duplicate Submission

{ "ok": true }

Invalid Signature

{ "ok": false, "error": "Invalid signature" }

Development

Testing

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"}}'

Monitoring

  • 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

Deployment

  1. Set Environment Variables: Configure NETLIFY_FORM_JWS and SLACK_WEBHOOK_URL
  2. Deploy to Val Town: The webhook is automatically deployed as an HTTP endpoint
  3. Configure Netlify: Set the webhook URL in your Netlify form settings
  4. Test: Submit a test form to verify the integration

Security Considerations

  • Secret Rotation: Regularly rotate the NETLIFY_FORM_JWS secret
  • 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

Troubleshooting

Common Issues

  1. 401 Unauthorized: Check that NETLIFY_FORM_JWS matches Netlify's webhook secret
  2. Missing Headers: Ensure Netlify is configured to send the required headers
  3. 500 Errors: Verify all environment variables are set correctly
  4. Email/Slack Failures: Check respective service configurations and credentials

Debug Steps

  1. Check Val Town request logs for detailed error information
  2. Verify webhook URL is correctly configured in Netlify
  3. Test with a minimal payload to isolate issues
  4. Ensure environment variables are properly set

License

This project is part of Preston-Werner Ventures' internal tooling.

FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
© 2026 Val Town, Inc.