Skip to content

Webhooks and API

FoxCLM integrates with external systems two ways: webhooks (push data out on events) and the REST API (pull data in and push data to FoxCLM from anywhere).

Webhooks

A webhook is a saved configuration - URL, HTTP method, auth, and payload template - that FoxCLM can fire on any workflow transition.

Adding a webhook config

  1. Go to Settings -> Webhooks / API (or /webhooks).
  2. Click + New Webhook.
  3. Fill in:
    • Name - internal label (e.g. "Slack #sales")
    • URL - the destination HTTPS endpoint
    • Method - POST (default), PUT, or PATCH
    • Headers - JSON object for auth headers, content type, etc.
    • Signing secret (optional) - FoxCLM signs each request with HMAC-SHA256
    • Payload template - the JSON body
  4. Save.

Payload templates

Use mustache-style placeholders. Example for an invoice webhook:

json
{
  "event": "invoice.paid",
  "invoice_id": {{id}},
  "invoice_number": "{{invoice_number}}",
  "amount": {{total}},
  "currency": "{{currency}}",
  "paid_at": "{{paid_at}}",
  "client_name": "{{client.name}}"
}

When the webhook fires, FoxCLM resolves placeholders against the entity and sends the rendered JSON.

HMAC signing

If you set a signing secret, FoxCLM adds an X-FoxCLM-Signature header:

X-FoxCLM-Signature: sha256=abc123...

Verify it in your receiver:

python
import hmac, hashlib

expected = hmac.new(
    secret.encode(),
    request.body,
    hashlib.sha256
).hexdigest()

if request.headers['X-FoxCLM-Signature'] != f'sha256={expected}':
    reject()

Firing webhooks from workflows

Add a call_webhook action to any transition and pick the saved webhook config. FoxCLM injects a _workflow metadata block into the payload automatically:

json
{
  "_workflow": {
    "from_status": "Sent",
    "to_status": "Paid",
    "entity_type": "invoice"
  },
  ...your template rendered here...
}

Scheduled webhooks

A webhook config can also be scheduled to fire on a cron interval, independent of workflow transitions. Set the schedule field to a cron expression (e.g. 0 9 * * * for daily at 9am).

Delivery logs

Every webhook fire is logged at Settings -> Webhooks / API -> Logs:

  • Timestamp
  • Webhook name
  • HTTP status returned
  • Response body (truncated)
  • Duration

Failed deliveries retry up to 3 times. After 3 failures, the log marks it as failed but does not retry further.

Raw API calls (no saved config)

If you don't want to save a webhook config, use the call_api workflow action instead. It takes URL, method, headers, and body template inline. See Workflow Actions.

REST API

FoxCLM exposes a REST API at /api/v1/ for all resources. Use it for custom integrations, bulk imports, or third-party tools.

Authentication

Two options:

  1. User JWT - log in via POST /api/v1/auth/login, use the returned token in Authorization: Bearer <token> for subsequent requests.
  2. API key - generate at Settings -> Webhooks / API -> API Keys, use in X-API-Key header.

API keys are scoped per workspace and can be revoked at any time.

Example: list clients

bash
curl https://your-instance.com/api/v1/clients \
  -H "Authorization: Bearer $TOKEN"

Example: create an invoice

bash
curl -X POST https://your-instance.com/api/v1/invoices \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "invoice_number": "INV-2026-001",
    "issue_date": "2026-05-01",
    "due_date": "2026-05-31",
    "currency": "USD",
    "client_ids": [42]
  }'

Common endpoints

ResourceEndpoints
ClientsGET/POST /clients, GET/PUT/DELETE /clients/:id
Sessions (events)GET/POST /events, GET/PUT/DELETE /events/:id
InvoicesGET/POST /invoices, GET/PUT/DELETE /invoices/:id
PayrollGET/POST /payroll, GET/PUT/DELETE /payroll/:id
StatusesGET/POST /statuses, GET/PUT/DELETE /statuses/:id
Custom fieldsGET/POST /customFields/defs, GET/PUT /customFields/values/:entity/:id

Response format:

json
{ "data": [...], "total": 120 }

Errors:

json
{ "message": "Client not found" }

All endpoints are scoped to your workspace (user_id is derived from the JWT / API key).

Common integration patterns

Slack notifications

Use call_webhook with Slack's incoming webhook URL:

json
{
  "text": "Invoice {{invoice_number}} paid: {{total}} {{currency}}"
}

Zapier / Make / n8n

Point a webhook at your automation tool's trigger URL. Fire on any transition you care about - the tool handles downstream logic.

Accounting export

Fire a webhook on invoice.paid that posts to your accounting software's API. The payload includes amount, client, date, and tax - everything needed to create an entry.

Data warehouse

Fire webhooks on every transition to a data collection endpoint. You now have a real-time event stream to analyse in BigQuery, Snowflake, or Postgres.

Next steps

FoxCLM Documentation