FieldCamp

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:

ResourceEvents
Clientclient.created, client.updated, client.deleted
Jobjob.created, job.updated, job.status_changed
Visitvisit.status_changed
Invoiceinvoice.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 POST requests with a JSON body;
  • verify the FieldCamp signature before processing the body; and
  • return a 2xx response 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"}
  }'
FieldRequiredBehavior
urlYesMust be a string beginning with https://.
eventsYesMust be a non-empty array containing only supported event names.
descriptionNoStores a label or note for the endpoint.
isActiveNoDefaults to true. Inactive endpoints do not receive events.
metadataNoStores 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 routePurpose
GET /api/v1/webhooksList 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}/deliveriesList 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 isActive to false to stop new deliveries without deleting the endpoint.
  • Set it back to true to 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:

HeaderValue
Content-Typeapplication/json
X-FieldCamp-SignatureLowercase hexadecimal HMAC-SHA256 signature.
X-FieldCamp-EventThe subscribed event name.
X-FieldCamp-DeliveryThe 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:

AttemptTiming
1Initial delivery
21 minute after the first failure
35 minutes after the second failure
430 minutes after the third failure
52 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}/deliveries

The response lists:

  • delivery id and event;
  • status and number of attempts;
  • last responseCode or errorMessage;
  • request duration;
  • createdAt and lastAttemptAt.

You can filter by:

  • status=pending|success|failed|retrying
  • event=<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 isActive is true.
  • Confirm the event name is included in the endpoint's events array.
  • 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.

On this page