FieldCamp

FieldCamp API Webhooks: Subscribe, Sign, and Verify Events

Set up FieldCamp API webhooks at /api/v1/webhooks to receive real-time events, verify HMAC signatures, and replay failed deliveries with confidence.

FieldCamp API webhooks let your apps and internal systems react in real time when jobs, visits, clients, invoices, estimates, payments, schedules, and team members change. Instead of polling for updates, you register a subscription at /api/v1/webhooks, FieldCamp delivers a signed event to your endpoint, and you verify the HMAC-SHA256 signature before processing the payload. This guide walks dispatchers, operations leads, and developers through registering webhook subscriptions, validating the X-FieldCamp-Signature header, handling retries with exponential backoff, inspecting deliveries, and recovering from auto-disable.

Webhooks are part of the FieldCamp API surface. If you are new to the API, start with the Quickstart and Authentication guides before subscribing to events.

What are webhooks in FieldCamp

A webhook is an HTTPS callback that FieldCamp sends to a URL you control whenever a specific event happens in your account. Webhooks turn the FieldCamp API into a push-based integration: your system stays in sync without running constant polling jobs, and downstream automations fire seconds after the change occurs in FieldCamp.

Typical use cases include:

  • Syncing newly created or updated clients to a CRM or data warehouse.
  • Pushing job status changes to a back-office ERP or accounting system.
  • Triggering invoice automations or accounting sync when a visit is completed.
  • Sending notifications to dispatchers when team assignments change or schedules shift.
  • Reconciling payments and deposits the moment money is captured.

If you are still designing your end-to-end flow, the FieldCamp workflow from lead to payment overview is a helpful primer on which events are most valuable to subscribe to.

Supported event types

FieldCamp emits 20 documented event types covering the resources that drive day-to-day field service operations. Each event has a stable name in the format resource.action, and each subscription can listen to one, several, or all of them.

Client events

  • client.created
  • client.updated
  • client.deleted

Job events

  • job.created
  • job.updated
  • job.status_changed
  • job.deleted

Invoice events

  • invoice.created
  • invoice.updated
  • invoice.paid

Estimate events

  • estimate.created
  • estimate.updated
  • estimate.approved

Payment events

  • payment.created
  • payment.refunded

Schedule and visit events

  • schedule.created
  • schedule.updated
  • schedule.canceled

Team member events

  • team_member.created
  • team_member.updated

Subscribe only to the events you actually process. Narrow subscriptions reduce noise, keep delivery logs readable, and lower load on your endpoint.

For the latest event catalog and schema changes, check the API changelog before going live.

Register a webhook subscription

You manage subscriptions through standard REST calls against the /api/v1/webhooks endpoint. Each subscription includes a destination url, an array of events, a unique secret used to sign every delivery, and an enabled flag you can toggle when you need to pause traffic.

Generate an API key

Generate or rotate an API key from your FieldCamp workspace and confirm scopes as described in Authentication. The key must have permission to manage webhook subscriptions.

Build a receiving endpoint

Stand up an HTTPS endpoint that responds to POST requests with a 2xx status code within a few seconds. Reject any non-HTTPS URL — FieldCamp does not deliver to plain HTTP.

Create the subscription

POST /api/v1/webhooks with the destination URL, the event list, and your shared secret. Store the returned subscription id so you can update, disable, or revoke it later.

Send a test event

Trigger a test delivery from the dashboard or by performing a real action (for example, creating a client). Confirm your endpoint received and acknowledged the event before promoting to production.

Example request body when creating a webhook:

{
  "url": "https://api.example.com/fieldcamp/webhooks",
  "events": ["job.status_changed", "invoice.paid", "schedule.updated"],
  "secret": "whsec_replace_with_random_string",
  "enabled": true
}

You can list, update, or delete subscriptions at any time:

  • GET /api/v1/webhooks — list every subscription on the account.
  • GET /api/v1/webhooks/:id — fetch a single subscription, including its current status.
  • PATCH /api/v1/webhooks/:id — update the URL, event list, or enabled flag.
  • DELETE /api/v1/webhooks/:id — permanently remove a subscription.

Treat your webhook configuration as code — keep the list in version control so changes are reviewable, just like the rest of your API integration.

Verify HMAC-SHA256 signatures

Every FieldCamp webhook delivery is signed so you can confirm the payload was sent by FieldCamp and was not modified in transit. The signature is computed with HMAC-SHA256 using the secret you provided when creating the subscription.

A delivery includes headers similar to:

  • X-FieldCamp-Signature: t=<unix_timestamp>,v1=<hex_signature>
  • X-FieldCamp-Event: job.status_changed
  • X-FieldCamp-Delivery-Id: <uuid>
  • X-FieldCamp-Webhook-Id: <subscription_id>

To verify the signature:

  1. Read the raw request body as bytes — do not re-serialize JSON, since whitespace changes will invalidate the signature.
  2. Parse the X-FieldCamp-Signature header into t (timestamp) and v1 (signature).
  3. Concatenate the timestamp, a period, and the raw body: signed_payload = t + "." + body.
  4. Compute HMAC_SHA256(secret, signed_payload) and compare it to the v1 value using a constant-time comparison.
  5. Reject deliveries older than five minutes to protect against replay attacks.

A minimal Node.js example:

const crypto = require("crypto");

function verify(req, secret) {
  const header = req.headers["x-fieldcamp-signature"];
  const [tPart, v1Part] = header.split(",");
  const timestamp = tPart.split("=")[1];
  const signature = v1Part.split("=")[1];

  const signedPayload = `${timestamp}.${req.rawBody}`;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(signedPayload)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(signature, "hex")
  );
}

Never log the webhook secret, and never accept events when verification fails. A failed signature check is the only reliable signal that a request did not originate from FieldCamp.

If you also use idempotency on outbound API calls, you can apply the same mindset here: treat the X-FieldCamp-Delivery-Id as an idempotency key so a retried delivery never double-processes.

Retries and exponential backoff

FieldCamp retries failed deliveries automatically. Any non-2xx status code, network error, or timeout is treated as a failure and re-queued using a fixed exponential-backoff schedule.

AttemptDelay after previous attempt
1Immediate (initial delivery)
21 minute
35 minutes
430 minutes
52 hours
624 hours

If your endpoint keeps failing for 3 consecutive days, FieldCamp automatically disables the subscription and stops sending new events to it. The subscription stays in your account with status: "disabled" so you can investigate and re-enable it after fixing the endpoint. Existing deliveries that have already exhausted their retry window are marked as failed and remain visible in the delivery log for replay.

Recommended endpoint behavior:

  • Acknowledge quickly: return 200 OK as soon as you have validated the signature and persisted the event for asynchronous processing.
  • Deduplicate by X-FieldCamp-Delivery-Id or by the payload's resource ID plus event type.
  • Use a queue or background worker for any work that takes longer than two seconds.

Pair webhooks with the FieldCamp rate limits and standardized errors so retries from your side, and ours, behave predictably.

Inspect deliveries with the deliveries endpoint

Every attempt FieldCamp makes is logged and available through the deliveries endpoint:

GET /api/v1/webhooks/:id/deliveries

Each entry includes the event type, attempt number, the HTTP status code your endpoint returned, the response body (truncated), the request and response timestamps, and the next retry time if the delivery is still in flight. Use the deliveries endpoint to:

  • Debug 4xx and 5xx responses without leaving FieldCamp.
  • Confirm a backfill after a deploy or a hotfix.
  • Investigate why a subscription was auto-disabled.
  • Replay deliveries while testing in staging.

You can filter the deliveries list by event type, status (succeeded, failed, pending), or time range. Combine this with the standardized error responses when triaging issues so your team has a single workflow for both API and webhook problems.

Re-enable a disabled subscription

If FieldCamp auto-disables a subscription after 3 days of failures, the fix has two parts:

Make the endpoint healthy

Inspect recent deliveries with GET /api/v1/webhooks/:id/deliveries. Look at the most recent failing status codes and response bodies, then fix the underlying issue — bad TLS certificate, blocked IP range, expired secret, application error, etc.

Re-enable the subscription

PATCH /api/v1/webhooks/:id with { "enabled": true }. FieldCamp resumes sending new events immediately. Deliveries that already aged out of the retry window are not automatically replayed.

Backfill what you missed

Use the API to backfill anything created or changed during the outage. The Jobs, Clients, and Visits resources all support filtered list queries you can use for this.

Security best practices

A webhook endpoint is a public surface, so harden it before you go live.

  • Terminate TLS with a valid certificate; reject HTTP entirely.
  • Validate the HMAC signature before parsing the body or running any business logic.
  • Restrict the endpoint to only the event types you registered for and reject unexpected X-FieldCamp-Event values.
  • Rotate the webhook secret on a schedule, and immediately if you suspect compromise. Rotate by PATCHing the subscription with a new secret.
  • Avoid IP allowlisting as your only defense — outbound IPs may change; treat the signature as the authoritative check.
  • Keep raw request bodies available to your verification function — many frameworks parse JSON before you get a chance to hash the original bytes.

Test, monitor, and operate

Once you have a verified subscription, treat it like any other production integration.

During implementation, watch the delivery logs for 4xx responses from your endpoint, set up alerting on consecutive failures (especially anything trending toward the 3-day auto-disable threshold), and replay key deliveries after every deploy of your consumer. If you are connecting webhooks to dispatching workflows or notifications, the getting started with FieldCamp's workflow builder guide is a useful complement — many teams use FieldCamp workflows for in-app automations and webhooks for cross-system sync.

Troubleshooting and FAQs

Why was my subscription disabled?
FieldCamp auto-disables a webhook after 3 consecutive days of failed deliveries. Open GET /api/v1/webhooks/:id/deliveries, find the failing status codes, fix your endpoint, then PATCH the subscription with { "enabled": true }. Backfill any events you missed during the outage using the resource APIs.

My signature check keeps failing — what should I look at first?
Almost every signature mismatch comes from mutating the raw request body before hashing. Make sure your framework gives you the raw bytes (Express needs express.raw({ type: "application/json" }), FastAPI needs await request.body(), etc.). Then confirm you concatenated timestamp + "." + raw_body and are comparing against the v1= portion of X-FieldCamp-Signature, not the full header.

Do webhooks replace polling the API?
For most resource changes, yes. You should still use the API to bootstrap data, page through historical records, and reconcile after outages, but day-to-day sync runs from webhook events.

Can I subscribe to all 20 events with one subscription?
You can, but multiple subscriptions scoped to specific event groups (for example, one for jobs and schedules, another for invoices and payments) are easier to operate, especially when different downstream systems own different parts of your stack.

Does FieldCamp guarantee event ordering?
No. Retries can cause later events to arrive before earlier ones. Always trust the resource version or timestamps in the payload rather than the delivery order when reconciling state.

What happens after the last retry?
After the 24-hour retry (six attempts total), the delivery is marked failed in the log and is not retried again. The subscription itself stays enabled unless the 3-day failure threshold is also crossed. Use the deliveries endpoint to replay manually once the endpoint is healthy.

On this page