P
ProFormsDocs

Inbound Webhooks

Accept form submissions from any external source — custom HTML forms on your website, Google Ads lead forms, Zapier, Make, or any system that can send an HTTP POST. No embed script needed. Just point your form's action URL at your webhook endpoint.

â„šī¸
Inbound webhooks auto-create forms from the incoming data. You don't need to build a form in ProForms first — just send data and it figures out the fields.

How It Works

  1. Create a webhook in your site's Integrations tab
  2. Copy the webhook URL and secret key
  3. Point your external form or integration at that URL
  4. ProForms receives the data, auto-creates a form (if needed), and stores the submission
  5. Email notifications, lead qualification, and outbound webhooks all fire as normal

Endpoint

URL
POST https://proforms.io/api/v1/incoming/{webhookId}?key={secretKey}

You can also pass the key as a header instead of a query parameter:

Header Auth
X-Webhook-Key: your_secret_key

Custom HTML Forms

The most common use case. Drop a plain HTML form on any website and have submissions flow into ProForms — with email notifications, spam protection, and lead management.

Basic Example

HTML
<form action="https://proforms.io/api/v1/incoming/YOUR_WEBHOOK_ID?key=YOUR_SECRET_KEY" method="POST">
  <input type="text" name="name" placeholder="Your name" required />
  <input type="email" name="email" placeholder="Email address" required />
  <input type="tel" name="phone" placeholder="Phone number" />
  <textarea name="message" placeholder="How can we help?"></textarea>

  <!-- Honeypot spam protection (hidden from real users) -->
  <input type="text" name="_hp" style="display:none" tabindex="-1" autocomplete="off" />

  <button type="submit">Send</button>
</form>

That's it. ProForms will:

  • Auto-detect field types (email, phone, text) from the data
  • Create a form in your site with matching fields
  • Store the submission and send email notifications
  • Score for spam (honeypot, timing, rate limiting, bot detection)

With Redirect

Add a _redirect hidden field to send users to a thank-you page after submission:

HTML
<form action="https://proforms.io/api/v1/incoming/YOUR_WEBHOOK_ID?key=YOUR_SECRET_KEY" method="POST">
  <input type="text" name="name" placeholder="Full name" required />
  <input type="email" name="email" placeholder="Email" required />
  <input type="text" name="company" placeholder="Company" />
  <select name="service">
    <option value="">Select a service</option>
    <option value="SEO">SEO</option>
    <option value="Web Design">Web Design</option>
    <option value="Google Ads">Google Ads</option>
  </select>

  <!-- Redirect after submission -->
  <input type="hidden" name="_redirect" value="https://yoursite.com/thank-you" />

  <!-- Name the auto-created form -->
  <input type="hidden" name="_form" value="Service Inquiry" />

  <!-- Honeypot -->
  <input type="text" name="_hp" style="display:none" tabindex="-1" autocomplete="off" />

  <button type="submit">Request Quote</button>
</form>

Special Fields

Fields prefixed with _are control fields — they're not stored in the submission data.

FieldTypeDescription
_redirectURLRedirect the user to this URL after successful submission (303 redirect). A ?ref= param is appended with the reference ID.
_formstringName for the auto-created form. If omitted, uses the webhook name.
_hphiddenHoneypot field. Must be empty — if filled (by bots), submission is silently marked as spam.

Google Ads Lead Form Extensions

Connect Google Ads lead form extensions directly to ProForms. When someone fills out a lead form on your ad, the data flows straight into ProForms for tracking and notifications.

Setup Steps

  1. Create a webhookin your site's Integrations tab. Set the source to Google Ads if available, or use the default.
  2. In Google Ads, go to your campaign → Assets → Lead Form Extension → Edit.
  3. Under "Lead delivery", select Webhook.
  4. Webhook URL:
    URL
    https://proforms.io/api/v1/incoming/YOUR_WEBHOOK_ID
  5. Key:Paste your webhook secret key into the Google Ads "Key" field. Google sends this as google_key in the payload body.
  6. Send test lead— use Google's "Send test data" button to verify the connection.

Google Ads Payload Format

Google Ads sends lead data in a specific format. ProForms auto-detects and parses it:

Google Ads Payload
{
  "lead_id": "TeSter-9999999999-0000000000-0",
  "campaign_id": 12345678901,
  "form_id": 12345678901,
  "gcl_id": "CjwKCAjw...",
  "google_key": "YOUR_SECRET_KEY",
  "user_column_data": [
    { "column_id": "FULL_NAME", "string_value": "Jane Smith" },
    { "column_id": "EMAIL", "string_value": "jane@example.com" },
    { "column_id": "PHONE_NUMBER", "string_value": "+14155551234" },
    { "column_id": "COMPANY_NAME", "string_value": "Smith Co" },
    { "column_id": "POSTAL_CODE", "string_value": "84401" }
  ],
  "api_version": "1.0",
  "is_test": true
}

Supported Google Ads Fields

Column IDMaps To
FULL_NAMEName field
FIRST_NAMEName / Text field
LAST_NAMEName / Text field
EMAILEmail field
PHONE_NUMBERPhone field
COMPANY_NAMECompany / Text field
STREET_ADDRESSAddress / Text field
CITYText field
STATEText field
POSTAL_CODEText field
COUNTRYText field
â„šī¸
System fields like lead_id, gcl_id, campaign_id, and form_id are stored in submission metadata — not as form fields. They appear in the submission detail view and API responses.

JSON API (Zapier, Make, Custom Code)

Send a JSON POST from any system — Zapier, Make (Integromat), n8n, or your own backend.

cURL
curl -X POST "https://proforms.io/api/v1/incoming/YOUR_WEBHOOK_ID?key=YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "801-555-1234",
    "service": "SEO",
    "message": "Interested in monthly SEO services"
  }'

Or pass the key as a header:

cURL (header auth)
curl -X POST "https://proforms.io/api/v1/incoming/YOUR_WEBHOOK_ID" \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Key: YOUR_SECRET_KEY" \
  -d '{ "name": "Jane Smith", "email": "jane@example.com" }'

Nested Data

If your payload has a data object, ProForms will use it as the submission fields:

JSON
{
  "data": {
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "801-555-0000"
  }
}

Response

Success (JSON)

200 OK
{
  "success": true,
  "submissionId": "sub_abc123...",
  "referenceId": "PF-42",
  "fieldsMapped": ["name", "email", "phone", "message"]
}

Success (HTML Form with _redirect)

When a _redirect field is present, returns a 303 See Other redirect to the specified URL with ?ref=PF-42 appended.

Errors

StatusMeaning
400Invalid body or no data fields found
401Missing or invalid secret key
403Webhook disabled or site inactive
404Webhook not found

Spam Protection

Inbound webhooks have built-in spam scoring. Submissions are scored 0–100 and anything above 70 is marked as spam.

SignalScore
Honeypot filled (_hp field has value)+100 (instant spam)
Submission under 2 seconds+40
Missing Referer header+30
Bot user agent+30
Duplicate content (same IP, same data)+25
Rate limit exceeded (5/min or 20/hr per IP)+20
Excessive URLs in text fields+20
Spam phrases detected+10 each (cap 30)
â„šī¸
Spam submissions are still stored — they're just flagged. You can review and unflag them in the submissions list. This prevents false positives from silently dropping real leads.

Auto-Created Forms

When a webhook receives data and no form is assigned, ProForms automatically:

  • Creates a form with fields inferred from the incoming data (email detection, phone detection, etc.)
  • Names it using the _form field value, or falls back to the webhook name
  • Links the webhook to that form for all future submissions
  • Evolves the schema — if a later submission includes new fields, they're added to the form automatically

You can also pre-assign a form to a webhook in the Integrations settings. In that case, incoming data is mapped to existing form fields by key name, label, or field type.

Verification Endpoint

Some services ping webhooks with a GET request to verify they're reachable:

GET
GET https://proforms.io/api/v1/incoming/YOUR_WEBHOOK_ID
Response
{
  "success": true,
  "webhook": "Contact Form",
  "status": "active"
}

WordPress Example

Add this to any WordPress page or post using a Custom HTML block:

WordPress Custom HTML Block
<form action="https://proforms.io/api/v1/incoming/YOUR_WEBHOOK_ID?key=YOUR_SECRET_KEY" method="POST" style="max-width: 500px;">
  <p>
    <label>Name</label><br/>
    <input type="text" name="name" required style="width: 100%; padding: 8px;" />
  </p>
  <p>
    <label>Email</label><br/>
    <input type="email" name="email" required style="width: 100%; padding: 8px;" />
  </p>
  <p>
    <label>Phone</label><br/>
    <input type="tel" name="phone" style="width: 100%; padding: 8px;" />
  </p>
  <p>
    <label>Message</label><br/>
    <textarea name="message" rows="4" style="width: 100%; padding: 8px;"></textarea>
  </p>

  <!-- Spam protection -->
  <input type="text" name="_hp" style="display:none" tabindex="-1" autocomplete="off" />

  <!-- Redirect to thank you page -->
  <input type="hidden" name="_redirect" value="https://yoursite.com/thank-you/" />
  <input type="hidden" name="_form" value="Contact Form" />

  <p><button type="submit" style="padding: 10px 24px; background: #10B981; color: white; border: none; border-radius: 6px; cursor: pointer;">Submit</button></p>
</form>
💡
This works with any WordPress theme — no plugins required. The form submits directly to ProForms and redirects back to your thank-you page. Style it with your theme's CSS or inline styles.

Webhook Lifecycle

Webhooks can be archived and restored. An archived webhook is disabled and returns a 410 Gone response when it receives submissions. This lets you deactivate a webhook without losing its configuration or submission history.

  • Active — Accepts submissions normally
  • Disabled — Returns 403 Forbidden (webhook exists but is turned off)
  • Archived — Returns 410 Gone (soft-deleted, restorable)
  • Deleted — Returns 404 Not Found (permanently removed)

To manage webhook lifecycle (create, archive, restore, delete), see the Manage Webhooks API.

Accepted Content Types

Content-TypeUse Case
application/jsonAPI calls, Zapier, Make, custom code
application/x-www-form-urlencodedHTML <form> submissions (default browser behavior)
multipart/form-dataHTML forms with file fields (files are not stored — text fields only)