Appearance
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
- Go to Settings -> Webhooks / API (or
/webhooks). - Click + New Webhook.
- 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
- 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:
- User JWT - log in via
POST /api/v1/auth/login, use the returned token inAuthorization: Bearer <token>for subsequent requests. - API key - generate at Settings -> Webhooks / API -> API Keys, use in
X-API-Keyheader.
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
| Resource | Endpoints |
|---|---|
| Clients | GET/POST /clients, GET/PUT/DELETE /clients/:id |
| Sessions (events) | GET/POST /events, GET/PUT/DELETE /events/:id |
| Invoices | GET/POST /invoices, GET/PUT/DELETE /invoices/:id |
| Payroll | GET/POST /payroll, GET/PUT/DELETE /payroll/:id |
| Statuses | GET/POST /statuses, GET/PUT/DELETE /statuses/:id |
| Custom fields | GET/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
- Workflow Actions - the
call_webhookandcall_apiactions - Workflows & Statuses - the transitions that trigger webhooks
