FieldCamp API Webhooks: Configure and Verify Events
Create FieldCamp webhook endpoints, subscribe to the supported event set, verify HMAC signatures, update endpoints, and inspect delivery attempts.
FieldCamp webhooks send an HTTPS POST request to your endpoint when a subscribed event occurs. Every delivery includes an HMAC-SHA256 signature, the event name, and a delivery ID.
Before you start, create an API key with the webhooks:manage scope. See FieldCamp API authentication for supported headers and scope behavior.
Supported events
Webhook endpoints can subscribe to these event names:
| Resource | Events |
|---|---|
| Client | client.created, client.updated, client.deleted |
| Job | job.created, job.updated, job.status_changed |
| Visit | visit.status_changed |
| Invoice | invoice.created, invoice.updated, invoice.paid |
Use client, job, and invoice resource identifiers when reconciling webhook activity with API data.
FieldCamp rejects an endpoint request containing any other event name.
Create a webhook endpoint
Your receiving URL must:
- begin with
https://; - accept
POSTrequests with a JSON body; - verify the FieldCamp signature before processing the body; and
- return a
2xxresponse within 30 seconds.
Create the endpoint with POST /api/v1/webhooks:
curl -X POST https://api.fieldcamp.ai/api/v1/webhooks \
-H "X-Api-Key: $FIELDCAMP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/webhooks/fieldcamp",
"events": ["job.status_changed", "invoice.paid"],
"description": "Operations sync",
"isActive": true,
"metadata": {"environment": "production"}
}'| Field | Required | Behavior |
|---|---|---|
url | Yes | Must be a string beginning with https://. |
events | Yes | Must be a non-empty array containing only supported event names. |
description | No | Stores a label or note for the endpoint. |
isActive | No | Defaults to true. Inactive endpoints do not receive events. |
metadata | No | Stores your own JSON metadata with the endpoint. |
FieldCamp generates the signing secret. Do not send a secret in the create request. The response returns the generated secret once, together with the endpoint record.
Store the returned webhook secret immediately. It is omitted from later list and detail responses.
List and inspect endpoints
Use these routes with a key that has webhooks:manage:
| Method and route | Purpose |
|---|---|
GET /api/v1/webhooks | List endpoints for the current FieldCamp account. |
GET /api/v1/webhooks/{id} | Get one endpoint and its delivery totals for the previous 24 hours. |
GET /api/v1/webhooks/{id}/deliveries | List delivery records for one endpoint. |
The list routes accept page and limit. The default limit is 30 and the maximum is 100.
Update or disable an endpoint
Use PUT /api/v1/webhooks/{id}. The accepted fields are url, events, description, isActive, and metadata.
curl -X PUT https://api.fieldcamp.ai/api/v1/webhooks/$WEBHOOK_ID \
-H "X-Api-Key: $FIELDCAMP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": ["job.updated", "job.status_changed"],
"isActive": false
}'- Set
isActivetofalseto stop new deliveries without deleting the endpoint. - Set it back to
trueto resume matching new events. - If you change
url, FieldCamp generates a new signing secret and includes it in that update response. Replace the old secret in your receiver before relying on deliveries to the new URL.
The update method is PUT, not PATCH.
Delete an endpoint
Use DELETE /api/v1/webhooks/{id}. Deleting an endpoint also deletes its stored delivery records and cannot be used as a temporary pause. Use isActive: false when you want to keep the configuration and history.
Verify the signature
FieldCamp sends these headers with each delivery:
| Header | Value |
|---|---|
Content-Type | application/json |
X-FieldCamp-Signature | Lowercase hexadecimal HMAC-SHA256 signature. |
X-FieldCamp-Event | The subscribed event name. |
X-FieldCamp-Delivery | The unique delivery record ID. |
The signature is HMAC-SHA256 over the exact JSON request body using the endpoint secret. It does not include a timestamp prefix or v1= wrapper.
import crypto from 'node:crypto';
export function verifyFieldCampWebhook(rawBody, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
const expectedBytes = Buffer.from(expected, 'hex');
const receivedBytes = Buffer.from(signature || '', 'hex');
return (
expectedBytes.length === receivedBytes.length &&
crypto.timingSafeEqual(expectedBytes, receivedBytes)
);
}Pass the raw request-body string to the verifier before changing or re-serializing it. Reject the request when the signature is missing or does not match.
Use X-FieldCamp-Delivery as an idempotency key in your receiver so a retry does not perform the same downstream action twice.
Handle delivery attempts
FieldCamp treats any non-2xx response, network error, or 30-second timeout as a failed attempt. Each delivery has a maximum of five attempts in total:
| Attempt | Timing |
|---|---|
| 1 | Initial delivery |
| 2 | 1 minute after the first failure |
| 3 | 5 minutes after the second failure |
| 4 | 30 minutes after the third failure |
| 5 | 2 hours after the fourth failure |
A successful attempt sets the delivery status to success. A failure that still has attempts remaining sets it to retrying; the fifth failed attempt sets it to failed.
The current webhook API does not provide a manual replay route or automatically disable an endpoint after repeated failures. Recover missed changes through the relevant resource API after fixing your receiver.
Inspect deliveries
Request:
GET /api/v1/webhooks/{id}/deliveriesThe response lists:
- delivery
idandevent; statusand number ofattempts;- last
responseCodeorerrorMessage; - request
duration; createdAtandlastAttemptAt.
You can filter by:
status=pending|success|failed|retryingevent=<supported-event-name>page=<number>limit=<1-100>
The delivery listing does not return the original payload, a response body, or a replay control.
Troubleshooting
Signature verification fails
- Verify the bare hexadecimal value from
X-FieldCamp-Signature. - Hash the exact received body, not a parsed and re-serialized object.
- Confirm you stored the secret returned by the latest create or URL-change response.
- Do not prepend a timestamp or parse a
v1=value; those are not part of this contract.
The endpoint receives no events
- Confirm
isActiveistrue. - Confirm the event name is included in the endpoint's
eventsarray. - Confirm the action occurred in the same FieldCamp account that owns the API key and endpoint.
Deliveries remain failed
Inspect the delivery's response code and error message, correct the receiving service, then reconcile any missed resource changes through the API.
Related articles
FieldCamp API Rate Limits and Throttling Headers
Understand FieldCamp API rate limits, the 60 RPM sliding window, throttling headers, and how to handle 429 errors in production integrations.
FieldCamp Webhook Events Catalog: 20 Event Types and Payloads
Reference for every FieldCamp webhook event, including sample payloads, required scopes, and tips for building reliable webhook receivers.