Introduction to Webhooks
How pro-Forms receives real-time data from third-party applications via webhooks, and how we authenticate the incoming requests.
What is a webhook?
A webhook is a way for a third-party application to notify us, automatically and in real time, when something happens on their side. Instead of our system repeatedly asking a partner's application "has anything changed yet?" (a pattern known as polling), a webhook lets them push a message to us the moment an event occurs.
In practice, a webhook is just an incoming HTTP request. When an event happens on a third-party application — for example, a record is created or updated in their system — that application sends an HTTP POST request containing details about the event to a URL that we've provided them in advance. That URL is our webhook receiving endpoint, and it lives on our servers.
In Short:
How webhooks work
POST request to our endpoint. The request must include the authentication headers described below and a JSON body describing the event.2xx status code to confirm successful receipt.2xx response promptly, most sending applications will retry delivery on their own backoff schedule — our endpoint should be built to handle receiving the same event more than once.
Why we use webhooks
- Real time — data arrives the moment an event happens on the partner's side, rather than on our next poll cycle.
- Efficient — no need for us to repeatedly call a partner's API to check for changes that usually haven't happened.
- Decoupled — we can ingest events from third-party systems without needing constant, direct access to their internal data.
Authentication in Webhooks
Because our webhook receiving endpoint is a publicly reachable URL, every incoming request must prove that it genuinely came from an authorized third-party application before we act on it. We require two credentials together, and our endpoint checks both before trusting a request.
1. Basic Authentication (pro-Forms credentials)
Every incoming webhook request must include an HTTP Authorization header using Basic Authentication, containing a valid pro-Forms username and password. The credentials are Base64-encoded together as username:password in the header, per the standard HTTP Basic Auth scheme.
2. API token (X-API-Token header)
In addition to Basic Authentication, every incoming request must include a custom X-API-Token header carrying an API token we've issued to your Workgroup. This token is generated and managed separately from the pro-Forms password, and should be treated by the sending application as a secret credential in its own right.
Both checks are requiredWe only treat an incoming request as authenticated if the pro-Forms username/password pair and the X-API-Token value are both valid. Our endpoint rejects the request (returns 401 Unauthorized) if either credential is missing or incorrect.
Required headers
| Header | Purpose | Example |
|---|---|---|
Authorization |
HTTP Basic Auth: Base64-encoded username:password for the pro-Forms user account |
Basic cHJvZm9ybXN1c2VyOnNlY3JldHBhc3M= |
X-API-Token |
API token we issued to your workgroup | X-API-Token: 7f3a9c2e-4b1d-4e8a-9c11-2d6f0a5b8e77 |
Content-Type |
Format of the request body | Content-Type: application/json |
Example incoming webhook request
This is what we expect a third-party application to send to our webhook receiving endpoint:
POST /webhooks/incoming HTTP/1.1
Host: webhooks.oursystem.example.com
Content-Type: application/json
Authorization: Basic cHJvZm9ybXN1c2VyOnNlY3JldHBhc3M=
X-API-Token: 7f3a9c2e-4b1d-4e8a-9c11-2d6f0a5b8e77
{
"event": "record.created",
"event_id": "evt_8f21c9a0",
"timestamp": "2026-08-17T09:42:11Z",
"data": {
"record_id": "r_10432",
"source_app": "partner-crm",
"fields": {
"name": "Jane Doe",
"email": "jane.doe@example.com"
}
}
}
Note: The credentials above are illustrative placeholders, not real values. Actual pro-Forms credentials and API tokens issued to integration partners are managed by your account administrator.
Handling credentials safely
- Validate the
AuthorizationandX-API-Tokenheaders on every incoming request before processing the payload — never trust the request body alone. - Only accept webhook deliveries over HTTPS, so credentials are never received in plain text.
- Issue a distinct pro-Forms account and API token per integration partner, so a single credential can be rotated or revoked without affecting other partners.
- Rotate a partner's API token periodically, and immediately if you suspect it has been exposed.
- Log authentication failures on incoming requests so misconfigured or compromised partner integrations are easy to spot.
Responding to a webhook
Once our endpoint has validated an incoming request, it should respond quickly so the sending application's connection isn't held open while we process the payload:
- 2xx Return within a few seconds to acknowledge successful receipt.
200 OKor204 No Contentare both fine. - 401 Return if authentication fails (missing/invalid pro-Forms credentials or API token).
- 4xx / 5xx Any other error response, or no response at all, will typically cause the sending application to retry delivery on its own schedule.
Troubleshooting
| Symptom | Likely cause |
|---|---|
A partner reports their webhook calls to us are being rejected with 401 |
Our endpoint is failing to validate the request — check that the partner is sending both a correct pro-Forms Authorization header and a current X-API-Token. The token may have been rotated or revoked on our side. |
| We receive the same event more than once | The sending application likely didn't receive a 2xx from us in time and retried. Make sure our processing is idempotent using the event_id. |
| We're not receiving any events from a partner | Confirm the partner has configured their webhook to point at the correct endpoint URL, and that outbound requests from their network can reach us (no firewall/allow-list blocking). |