Skip to main content

Webhooks

Webhook endpoints

Subscribe a URL to events, such as a client added or a check-in submitted, and manage it.

A webhook endpoint is a URL HubFit sends events to as they happen: a client added, a check-in or questionnaire submitted, a workout completed, a package purchased. Each event carries ids, not the record: fetch it with your own key.

Only a key that belongs to the workspace's owner or an admin, with webhooks:write, manages endpoints. It sees every endpoint in the workspace, including those added in Settings > API, but changes only the ones it made. How deliveries are signed, retried and turned off is in Webhooks.

Attributes

  • idstring

    Its unique ID.

  • namestring
  • urlstring

    The full URL for an endpoint this key made. For any other, only its origin, since a URL like a Zapier hook's runs whatever it's attached to.

  • eventsarray of enums
    Known valuesclient.createdcheck_in_submission.createdcompleted_workout.createdpackage_purchase.createdquestionnaire_submission.created
  • statusenum

    An enabled endpoint gets nothing while the workspace is off a plan with webhooks, unpaid or suspended, and nothing from that time once it's back.

    Known valuesenableddisabled
  • disabledReasonenumnullable

    Why the endpoint is disabled, and null while it's enabled. These can be turned back on: manual, turned off with status: disabled or in Settings; gone, after a 410 reply; and failing, after 5 days without a success. These stop it for good, with every other endpoint its key made: api_key_revoked, its key was revoked; api_key_expired, its key expired; coach_removed, the key's coach was removed from the workspace or their account was deleted; and role_changed, the key's coach was made a Standard member.

    Known valuesmanualgonefailingapi_key_revokedapi_key_expiredcoach_removedrole_changed
  • lastDeliveryobjectnullable
    Show 3 child attributes
    • delivered after a 2xx reply. retry when the attempt failed and another is scheduled, failed when it failed with no attempt left. gone after a 410 reply, which turns the endpoint off. blocked when the URL led to an address webhooks can't be sent to, such as a private one: it isn't retried.

      Known valuesdeliveredretryfailedgoneblocked
    • statusCodeintegernullable

      The reply's status. null if there was none, such as a timeout.

    • attemptedAttimestamp
  • createdAttimestamp

    When it was created.

  • updatedAttimestamp

    When it last changed.

Webhook endpoint object
{
  "id": "6ad6affd3db7e9fc3db656fb",
  "name": "CRM",
  "url": "https://example.com/hubfit-webhooks",
  "events": ["client.created", "check_in_submission.created"],
  "status": "enabled",
  "disabledReason": null,
  "lastDelivery": {
    "outcome": "delivered",
    "statusCode": 200,
    "attemptedAt": "2026-10-26T14:32:05.000Z"
  },
  "createdAt": "2026-03-02T15:04:11.000Z",
  "updatedAt": "2026-10-26T09:12:40.000Z"
}

The JSON body of every webhook request. See Webhooks for its headers and how to verify it.

Attributes

  • idstring

    The event's id, as in webhook-id.

  • typeenum

    The event type. New types can appear.

    Known valuesclient.createdcheck_in_submission.createdcompleted_workout.createdpackage_purchase.createdquestionnaire_submission.created
  • createdAttimestamp

    When it was created.

  • dataobject

    The record the event is about. Fetch it with your key to read it as it is now.

    Show 2 child attributes
    • idstring

      The record's id.

    • clientIdstring

      The client it belongs to. For client.created, the client itself.

Event object
{
  "id": "evt_6ad6af72e7830e73e784a170",
  "type": "check_in_submission.created",
  "createdAt": "2026-10-26T14:32:06.000Z",
  "data": {
    "id": "6ad6af25540e6a26540ffd23",
    "clientId": "6ad6af41d3199442d31b2743"
  }
}
GET/v1/webhook-endpoints

Every endpoint in the workspace, newest first, whole (a workspace has at most 10), made with any key or in Settings. An endpoint this key didn't make shows only the origin of its URL. Requires webhooks:write.

This endpoint takes no parameters.

Returns

The workspace's endpoints.

GET /v1/webhook-endpoints
curl https://api.hubfit.com/v1/webhook-endpoints \
  -H "Authorization: Bearer $HUBFIT_API_KEY"
Response200 OK
{
  "data": [
    {
      "id": "6ad6affd3db7e9fc3db656fb",
      "name": "CRM",
      "url": "https://example.com/hubfit-webhooks",
      "events": ["client.created", "check_in_submission.created"],
      "status": "enabled",
      "disabledReason": null,
      "lastDelivery": {
        "outcome": "delivered",
        "statusCode": 200,
        "attemptedAt": "2026-10-26T14:32:05.000Z"
      },
      "createdAt": "2026-03-02T15:04:11.000Z",
      "updatedAt": "2026-10-26T09:12:40.000Z"
    }
  ]
}
POST/v1/webhook-endpoints

Subscribes a URL to events. The endpoint is enabled at once and gets events from then on.

The URL must be HTTPS on port 443, with a public domain name (never an IP address) written in lowercase, and no user name, password or # fragment. Every event type needs the scope that reads its records (clients:read). The response carries the endpoint's signing secret, the only time the API shows it. A workspace has at most 10 endpoints. One key can't add the same URL twice: that's 409 webhook_endpoint_exists. Requires webhooks:write, and a key belonging to the workspace's owner or an admin: anyone else's gets 403 role_required. The endpoint gets events about every client, and stops for good (role_changed) if the key's coach is made a Standard member.

Headers

  • Any unique string, such as a UUID, up to 255 characters. Retrying with the same key within 24 hours returns the first response instead of repeating the write. See Idempotency.

Body parameters

  • namestringRequired

    What your team calls the endpoint, e.g. CRM. Can't be blank.

  • urlstringRequired

    Where to send events, e.g. https://example.com/hubfit-webhooks.

  • eventsarray of enumsRequired
    One ofclient.createdcheck_in_submission.createdcompleted_workout.createdpackage_purchase.createdquestionnaire_submission.created

Returns

The new endpoint, and its signing secret.

POST /v1/webhook-endpoints
curl -X POST https://api.hubfit.com/v1/webhook-endpoints \
  -H "Authorization: Bearer $HUBFIT_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CRM",
    "url": "https://example.com/hubfit-webhooks",
    "events": ["client.created", "check_in_submission.created"]
  }'
Response201 Created
{
  "data": {
    "id": "6ad6affd3db7e9fc3db656fb",
    "name": "CRM",
    "url": "https://example.com/hubfit-webhooks",
    "events": ["client.created", "check_in_submission.created"],
    "status": "enabled",
    "disabledReason": null,
    "lastDelivery": {
      "outcome": "delivered",
      "statusCode": 200,
      "attemptedAt": "2026-10-26T14:32:05.000Z"
    },
    "createdAt": "2026-03-02T15:04:11.000Z",
    "updatedAt": "2026-10-26T09:12:40.000Z"
  },
  "secret": "whsec_EXAMPLE+ONLY+notARealHubFitSigningSecret+00="
}
GET/v1/webhook-endpoints/{endpointId}

One endpoint in the workspace. If this key didn't make it, only the origin of its URL is shown. Requires webhooks:write.

Path parameters

  • endpointIdstringRequired

    A webhook endpoint id from GET /webhook-endpoints.

Returns

The endpoint.

GET /v1/webhook-endpoints/{endpointId}
curl https://api.hubfit.com/v1/webhook-endpoints/6ad6affd3db7e9fc3db656fb \
  -H "Authorization: Bearer $HUBFIT_API_KEY"
Response200 OK
{
  "data": {
    "id": "6ad6affd3db7e9fc3db656fb",
    "name": "CRM",
    "url": "https://example.com/hubfit-webhooks",
    "events": ["client.created", "check_in_submission.created"],
    "status": "enabled",
    "disabledReason": null,
    "lastDelivery": {
      "outcome": "delivered",
      "statusCode": 200,
      "attemptedAt": "2026-10-26T14:32:05.000Z"
    },
    "createdAt": "2026-03-02T15:04:11.000Z",
    "updatedAt": "2026-10-26T09:12:40.000Z"
  }
}
PATCH/v1/webhook-endpoints/{endpointId}

Changes only the fields you send. A new url takes effect at once. status: disabled stops it at once and cancels what's waiting to be sent. status: enabled turns a disabled endpoint back on, for events from then on, if its disabledReason is manual, gone or failing (otherwise 409 webhook_endpoint_disabled). Only an endpoint this key made can be changed; any other is 403 webhook_endpoint_read_only. Requires webhooks:write.

Path parameters

  • endpointIdstringRequired

    A webhook endpoint id from GET /webhook-endpoints.

Body parameters

  • namestring
  • urlstring
  • eventsarray of enums
    One ofclient.createdcheck_in_submission.createdcompleted_workout.createdpackage_purchase.createdquestionnaire_submission.created
  • statusenum
    One ofenableddisabled

Returns

The endpoint as it is now.

PATCH /v1/webhook-endpoints/{endpointId}
curl -X PATCH https://api.hubfit.com/v1/webhook-endpoints/6ad6affd3db7e9fc3db656fb \
  -H "Authorization: Bearer $HUBFIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "enabled"
  }'
Response200 OK
{
  "data": {
    "id": "6ad6affd3db7e9fc3db656fb",
    "name": "CRM",
    "url": "https://example.com/hubfit-webhooks",
    "events": ["client.created", "check_in_submission.created"],
    "status": "enabled",
    "disabledReason": null,
    "lastDelivery": {
      "outcome": "delivered",
      "statusCode": 200,
      "attemptedAt": "2026-10-26T14:32:05.000Z"
    },
    "createdAt": "2026-03-02T15:04:11.000Z",
    "updatedAt": "2026-10-26T09:12:40.000Z"
  }
}
DELETE/v1/webhook-endpoints/{endpointId}

Deletes the endpoint and cancels what's waiting to be sent to it. Only an endpoint this key made can be deleted (403 webhook_endpoint_read_only). Requires webhooks:write.

Path parameters

  • endpointIdstringRequired

    A webhook endpoint id from GET /webhook-endpoints.

Returns

It's deleted.

DELETE /v1/webhook-endpoints/{endpointId}
curl -X DELETE https://api.hubfit.com/v1/webhook-endpoints/6ad6affd3db7e9fc3db656fb \
  -H "Authorization: Bearer $HUBFIT_API_KEY"
Response200 OK
{
  "data": {
    "id": "6ad6af165d04c7155d033418",
    "deleted": true
  }
}