Skip to content

Delivery

This page describes how Crewsum delivers webhook events today. Build your endpoint for this behavior: one attempt per event, no retries, and no delivery IDs.

Crewsum sends each event as an HTTP POST to the webhook’s URL.

PartValue
BodyJSON with two fields: event (the event type, such as clients.created) and data (the payload). See the event reference.
x-timestampThe time Crewsum signed the request, in Unix seconds.
x-crewsum-signatureThe HMAC-SHA256 signature of the request. See Validating Webhook Signatures.
Content-TypeCurrently application/x-www-form-urlencoded, although the body is JSON. Read the raw body and parse it as JSON yourself.
{
"event": "clients.created",
"data": {
"clients": [{ "id": "client-ghi123jkl4567890", "name": "Northwind Logistics" }]
}
}

The example is shortened. The body has no event ID, delivery ID, or tenant ID.

  • Crewsum sends the event during the request that made the change: after the change is saved, and before Crewsum responds to the person or API client that made it.
  • If the request fails or is rejected before the change is saved, no event is sent.
  • Crewsum waits for your endpoint to respond. There is no timeout. A slow endpoint makes the Crewsum action that triggered the event slow, for the user in the app or for the API client.
  • If several webhooks subscribe to the same event, Crewsum sends to them one at a time.
  • Any status from 200 to 500 ends the delivery. Crewsum does not read the response body.
  • Crewsum does not retry. An event that your endpoint does not process, for example because it returned 500 or was offline, is not sent again.
  • If the connection fails, or your endpoint returns a status above 500 (such as 502 or 503), Crewsum stops sending that event. Webhooks that were still waiting for the same event do not receive it.

A failed delivery does not change the result of the action that triggered it. The change is still saved.

  • One action can send several events. They are sent one after another, in a fixed order. For example, creating a client in the app with projects, contacts, and tasks sends clients.created, then projects.created, project-contacts.created, tasks.created, and associations.created.
  • Events from different actions that happen at the same time can arrive in any order.
  • If order matters to you, compare the updatedAt value in the payload with the value you stored, or read the current record from the API.
  • Validate the signature first. Reject requests that fail with 401.
  • Respond quickly with 200. Put the event on a queue and process it after you respond. Because Crewsum waits for your response, slow processing slows down Crewsum for your users.
  • Return a 2xx status after you accept the event, even if you ignore that event type. Do not return a status above 500 on purpose: it stops delivery of that event to your other webhooks.
  • Make processing idempotent. There is no event ID. Use the record ID and updatedAt from data to detect events you have already processed.
  • Reconcile on a schedule. Crewsum does not retry or replay events. Use the API list endpoints, such as Get Clients or Get Timesheets, to find changes you missed while your endpoint was unavailable.
  • Handle the debug event. Send test and Send Event in Crewsum send {"event":"debug","data":{"message":"Debug Event"}}. Return 200 for it.