Webhooks
Overview
Feed Item objects are created when significant events occur in your account, such as class registrations, customer signups, and payments. These Feed Items can be delivered to your integration through Webhooks.
Webhooks notify integrations about new Feed Item objects by sending an HTTP POST request to a Webhook Destination (a configured URL). The request payload includes one or more Feed Item objects.
This document outlines the general concepts of Feed Items and Webhooks.
Webhook Delivery
Webhooks are delivered as HTTP POST requests to the URL defined in the Webhook Destination.
Your server must respond with a 2xx status code (e.g., 200 OK or 204 No Content) within 10 seconds.
You may also respond with a 410 Gone status to indicate that no further Webhooks should be sent to this destination.
We attempt delivery up to 5 times at increasing intervals (see Webhook Retries).
Key Notes
- Webhooks may be delivered out of order.
- Deliveries will not follow redirects. Responses such as
301or302will be treated as failed delivery attempts.
Headers
Each webhook POST request includes a TEAMUP-WEBHOOK-ID header containing a unique identifier for that webhook.
This ID remains the same across delivery attempts, making it useful for deduplication.
Webhook Retries
If your server does not respond with a 2xx or 410 status within 10 seconds, we retry delivery four more times at the following intervals:
- 1 minute
- 3 minutes
- 10 minutes
- 30 minutes
After the fifth attempt, no further delivery attempts are made.
Disabling a Webhook Destination
Responding with 410 Gone disables the Webhook Destination permanently. Once received, no further webhooks will be delivered to that destination.
Payload
The payload of a Webhook is a JSON object containing a list of Feed Item objects.
Currently, webhooks contain a single feed item, but in the future, multiple items may be included.
Sample payload:
{
"feed_items": [
{
"object": "feed_item",
"id": 13553027,
"timestamp": "2019-04-27T21:52.45",
"type": "event_registration.created",
"source": "standalone",
"resources": {
"customer": 818974,
"event": 14947247,
"business": 285151
}
}
]
}
Webhook Destinations
Webhook Destinations define where webhooks are sent.
Destinations can be configured to receive all or only specific Feed Item types that occur within a provider's account.
The Webhook Destination Object
| Attribute | Description |
|---|---|
object | Always "webhook_destination". |
id | Unique identifier for the object. |
url | The URL to which webhooks are delivered. |
feed_item_types | A list of Feed Item types to be notified about. The value * represents all types. |
application | The Application that the destination is associated with. |
Example:
{
"object": "webhook_destination",
"id": 53583,
"url": "https://example.com/receiver",
"feed_item_types": ["*"],
"application": 533
}
Setting Up a Webhook Destination
Webhook Destinations belong to an API Application, so you need an Application first. You can create and manage destinations in two ways: from the TeamUp business dashboard, or via the API. In both cases you need full admin access to the business.
From the Business Dashboard
- In your TeamUp business dashboard, go to Settings → Integrations → API Integration.
- Open the Application the destination should belong to (or create one).
- In the Webhook Destinations section, click Add Webhook Destination.
- Enter the URL webhooks should be delivered to, and choose whether to receive all event types or only specific ones.
- Save the destination. It becomes active immediately.
Via the API
Destinations can also be managed programmatically through the Webhook Destinations endpoints. To create one, send an authenticated POST request to /webhook_destinations:
{
"url": "https://example.com/receiver",
"feed_item_types": ["*"],
"application": 533
}
Use ["*"] to receive all Feed Item types, or list specific types (e.g. ["customer.created", "event_registration.created"]). See Authentication for how to authenticate API requests.
Before You Go Live
- The destination URL must be publicly reachable and able to accept
POSTrequests with a JSON body. If your framework applies CSRF protection to incoming requests, exempt the webhook route. - The URL must respond directly with a
2xx— redirects are treated as failed deliveries. - Only new activity is delivered. Creating a destination does not send historical Feed Items.
Verifying Deliveries
TeamUp webhooks are not signed. Delivery requests do not include a signature header, HMAC, or shared secret, so there is no built-in way to cryptographically verify that a request genuinely came from TeamUp. (Some third-party guides mention a teamup-signature header — no such header exists.)
Instead, we recommend the following pattern:
- Treat the payload as a notification, not as a source of truth. Use the webhook only as a signal that something changed.
- Re-fetch the referenced resources through the API. Each Feed Item's
resourcesobject contains the IDs of the related resources (customer, event, etc.). Fetch the current state of those resources with an authenticated API request before acting on the change. Since API requests are authenticated, a forged webhook cannot feed you false data — at worst it triggers an unnecessary lookup. - Use an unguessable receiver URL. Include a hard-to-guess path segment or query-string token in the destination URL, and reject requests that do not match it.
- Deduplicate using the
TEAMUP-WEBHOOK-IDheader so a replayed or retried request is not processed twice.
Troubleshooting Missed Deliveries
If your integration is not receiving webhooks (or is missing some), work through this checklist:
- Check the destination's status. A destination that has responded with
410 Gone— even once — is disabled and receives no further deliveries. Check the status in the dashboard (Settings → Integrations → API Integration, under the Application's Webhook Destinations section) or by retrieving the destination via the API. A disabled destination can be re-enabled by setting its status back toactive, but webhooks that occurred while it was disabled are not delivered retroactively. - Check the destination's
feed_item_types. The destination only receives the listed types (or all types when set to*). A missing type means those Feed Items are never sent to it. - Respond fast. Your server must return a
2xxwithin 10 seconds or the attempt counts as failed. Do any real processing asynchronously: acknowledge first, process after. - Return a
2xxdirectly. Redirects (301,302, etc.) are not followed and count as failed attempts — configure the destination with the final URL (including anyhttp→httpsor trailing-slash redirects your server performs). Any non-2xx, non-410response also counts as a failure. - Never return
410unintentionally.410 Gonepermanently disables the destination. Make sure error paths in your receiver (or your framework's default responses for unknown routes) cannot return it. - Accept the request format. Deliveries are
POSTrequests with a JSON body. Endpoints that rejectPOST, require CSRF tokens, or block unknown user agents will fail every attempt. - Know the retry window. Failed deliveries are retried up to 4 more times (5 attempts total) at 1, 3, 10, and 30 minute intervals — roughly 44 minutes end to end. After the fifth failed attempt the webhook is marked failed and there is no redelivery mechanism, manual or automatic.
- Recovering after an outage. Because missed webhooks cannot be replayed, recover by re-fetching the current state of the resources you care about through the API once your receiver is healthy again.
- Handle ordering and duplicates. Webhooks may arrive out of order, and retries can occasionally cause duplicates. Use the
TEAMUP-WEBHOOK-IDheader (stable across retry attempts) to deduplicate, and rely on API re-fetches rather than payload order to determine current state.
Feed Items
The Feed Item Object
| Attribute | Description |
|---|---|
object | Always "feed_item". |
id | Unique identifier for the object. |
timestamp | ISO 8601 timestamp when the activity occurred. |
type | The type of Feed Item (see Feed Item Types). |
source | Identifies a more specific trigger for event registration changes, such as enrolling from a waitlist or being removed due to a class cancellation. |
resources | Object containing references to related resources. |
Example:
{
"object": "feed_item",
"id": 13553027,
"timestamp": "2019-04-27T21:52.45",
"type": "event_registration.created",
"source": "standalone",
"resources": {
"customer": 818974,
"event": 14947247,
"business": 285151
}
}
Feed Item Types
This section lists all Feed Item types.
course_session.ended
Created when a course session ends.
Resources:
- course_session
- business
customer.created
Created when a new customer is created.
Resources:
- customer
- business
customer.invited
Created when a customer is invited to join a business (in addition to customer.created).
Resources:
- customer
- business
customer.signed_up
Created when a customer completes the signup process.
Resources:
- customer
- business
customer.updated
Created when a customer’s details (name, email, field values, etc.) are updated.
Resources:
- customer
- business
customer.deleted
Created when a customer is deleted.
Resources:
- customer
- business
customer_membership.created
Created when a customer membership is added (via purchase or manually from the business dashboard).
Resources:
- customer
- business
- customer_membership
customer_membership.started
Created when a membership becomes valid (for future start dates, this occurs on the start date).
Resources
- customer
- business
- customer_membership
customer_membership.ended
Created when a customer membership ends. Applies only to recurring and prepaid plans.
Resources:
- customer
- business
- customer_membership
customer_membership.cancelled
Created when a customer cancels a membership. Applies only to recurring plans.. This occurs when a user clicks Cancel in TeamUp.
Cancellation sets an expiration date, which will later trigger a customer_membership.ended Feed Item.
Resources:
- customer
- business
- customer_membership
customer_membership.completed
Created when a pack membership has reached its usage limit.
Resources:
- customer
- customer_membership
- business
customer_referral.created
Created when a customer signs up using a referral.
Resources:
- customer
- business
- referrer
customer_referral.confirmed
Created when a referred customer completes the necessary steps to confirm the referral.
Resources:
- customer
- business
- referrer
event.ended
Created when a class/appointment/rental ends.
Resources:
- event
- business
event_registration.created
Created when a customer registers for an event. Includes various sources indicating how the registration occurred.
Sources:
standalone: Not associated with any of the below.- Resources: event, customer, business
waitlist: Automatically from the waitlist.- Resources: event, customer, business
reservation: As part of a recurring reservation.- Resources: event, customer, reservation, business
block_booking: As part of a block booking.- Resources: event, customer, business
event_registration.removed
Created when a customer is removed from an event.
Sources:
standalone: Not associated with any of the below.- Resources: event, customer, business
event_cancelled: Automatically from the waitlist.- Resources: event, customer, business
event_registration.late_cancelled
Created when a customer late cancels from an event. The customer’s membership usage is not refunded.
Resources:
- event
- customer
- business
event_registration.attended
Created when a customer is marked as attended.
Resources:
- event
- customer
- business
event_registration.noshowed
Created when a customer is marked as a no-show.
Resources
- event
- customer
- business
event_registration.waitlist.added
Created when a customer is added to the waitlist.
Resources:
- event
- customer
- business
event_registration.waitlist.removed
Created when a customer is removed from the waitlist.
Resources:
- event
- customer
- business
event_registration.waitlist.spot_reserved
Created when a customer’s waitlist spot is reserved.
Resources:
- event
- customer
- business
event_registration.waitlist.spot_expired
Created when a customer’s waitlist spot expires.
Resources:
- event
- customer
- business
event_registration.waitlist.spot_declined
Created when a customer declines a waitlist spot.
Source not used. Resources: event, customer, business.
lead_form.submitted
Created when a lead form is submitted.
Resources:
- customer
- business
- lead_form