Subscription Design Guide
This guide details how to design an efficient eventing architecture within the default SmartThings quota allocations. With 10 sinks, 10 subscriptions, 10 filters per subscription, and 10 capabilities per capability filter, you can monitor up to 1,000 distinct capabilities per account. This capacity supports most large-scale enterprise deployments
Filters within a subscription are evaluated with OR logic — an event is delivered if it matches any filter in the subscription.
Understanding the Quota Math
Each level of the eventing hierarchy multiplies your capacity:
| Resource | Quota | Multiplier Effect |
|---|---|---|
| Sinks per account | 10 | 10 distinct webhook endpoints |
| Subscriptions per account | 10 | 10 filter configurations (can point to same or different sinks) |
| Filters per subscription | 10 | 10 filter groups per subscription (OR logic) |
| Capabilities per capability filter | 10 | 10 capabilities per filter group |
| Event types per event type filter | 10 | 10 event types per filter group |
Maximum capability coverage per subscription: 10 filters × 10 capabilities = 100 capabilities
Maximum capability coverage per account: 10 subscriptions × 10 filters × 10 capabilities = 1,000 capabilities
Design Patterns
Pattern 1: Single Sink, Domain-Based Subscriptions
Best for: Most deployments where one webhook processes all events, organized by domain.
Subscription: HVAC ──┐
├──▶ Webhook Endpoint
Subscription: Security ──┤
│
Subscription: Energy ──┘
- HVAC Subscription
- Security Subscription
- Energy Subscription
{
"name": "HVAC-Events",
"sinkId": "your-sink-id",
"scope": "ACCOUNT",
"filters": [
{
"type": "CAPABILITY",
"capabilityFilter": {
"capabilities": [
{ "capability": "temperatureMeasurement" },
{ "capability": "thermostatCoolingSetpoint" },
{ "capability": "thermostatHeatingSetpoint" },
{ "capability": "thermostatMode" },
{ "capability": "thermostatOperatingState" },
{ "capability": "thermostatFanMode" },
{ "capability": "relativeHumidityMeasurement" }
],
"exclude": false
}
}
]
}
{
"name": "Security-Events",
"sinkId": "your-sink-id",
"scope": "ACCOUNT",
"filters": [
{
"type": "CAPABILITY",
"capabilityFilter": {
"capabilities": [
{ "capability": "lock" },
{ "capability": "lockCodes" },
{ "capability": "contactSensor" },
{ "capability": "motionSensor" },
{ "capability": "presenceSensor" },
{ "capability": "waterSensor" },
{ "capability": "doorControl" },
{ "capability": "multipleZonePresence" }
],
"exclude": false
}
}
]
}
{
"name": "Energy-Events",
"sinkId": "your-sink-id",
"scope": "ACCOUNT",
"filters": [
{
"type": "CAPABILITY",
"capabilityFilter": {
"capabilities": [
{ "capability": "powerConsumptionReport" },
{ "capability": "demandResponseLoadControl" },
{ "capability": "custom.energyType" },
{ "capability": "switch" },
{ "capability": "switchLevel" }
],
"exclude": false
}
}
]
}
Pattern 2: Multiple Sinks for Separate Back-End Systems
Best for: Routing different event types to different processing pipelines.
Multiple sinks can share the same webhook URL — there is no validation preventing it. Using distinct URLs is recommended so each back-end system can process its events independently, without needing to filter a shared stream itself.
Subscription: Critical Alerts ──▶ Alerting Service
Subscription: Telemetry ──▶ Data Pipeline
Subscription: Lifecycle ──▶ Asset Tracker
- Critical Alerts → Alerting Service
- Telemetry → Data Pipeline
- Lifecycle → Asset Tracker
{
"name": "Critical-Alerts",
"sinkId": "alerting-service-sink-id",
"scope": "ACCOUNT",
"filters": [
{
"type": "CAPABILITY",
"capabilityFilter": {
"capabilities": [
{ "capability": "waterSensor" },
{ "capability": "smokeDetector" },
{ "capability": "carbonMonoxideDetector" },
{ "capability": "tamperAlert" }
],
"exclude": false
}
}
]
}
{
"name": "Device-Telemetry",
"sinkId": "data-pipeline-sink-id",
"scope": "ACCOUNT",
"filters": [
{
"type": "CAPABILITY",
"capabilityFilter": {
"capabilities": [
{ "capability": "temperatureMeasurement" },
{ "capability": "relativeHumidityMeasurement" },
{ "capability": "powerConsumptionReport" },
{ "capability": "battery" }
],
"exclude": false
}
}
]
}
{
"name": "Device-Lifecycle",
"sinkId": "asset-tracker-sink-id",
"scope": "ACCOUNT",
"filters": [
{
"type": "EVENT_TYPE",
"eventTypeFilter": {
"eventTypes": [
{ "eventType": "DEVICE_LIFECYCLE_EVENT" }
],
"exclude": false
}
}
]
}
Pattern 3: Maximizing Capability Coverage
When you need to monitor many capabilities, use multiple filters within a single subscription. Each filter supports up to 10 capabilities. The system automatically evaluates all filters with OR logic — an event is delivered if it matches any one of the filters in the subscription.
{
"name": "Full-Coverage-Subscription",
"sinkId": "your-sink-id",
"scope": "ACCOUNT",
"filters": [
{
"type": "CAPABILITY",
"capabilityFilter": {
"capabilities": [
{ "capability": "battery" },
{ "capability": "lock" },
{ "capability": "lockCodes" },
{ "capability": "relativeHumidityMeasurement" },
{ "capability": "switch" },
{ "capability": "switchLevel" },
{ "capability": "temperatureMeasurement" },
{ "capability": "thermostatCoolingSetpoint" },
{ "capability": "thermostatFanMode" },
{ "capability": "thermostatHeatingSetpoint" }
],
"exclude": false
}
},
{
"type": "CAPABILITY",
"capabilityFilter": {
"capabilities": [
{ "capability": "thermostatMode" },
{ "capability": "thermostatOperatingState" },
{ "capability": "waterSensor" },
{ "capability": "powerConsumptionReport" },
{ "capability": "demandResponseLoadControl" },
{ "capability": "custom.energyType" },
{ "capability": "contactSensor" },
{ "capability": "motionSensor" },
{ "capability": "presenceSensor" },
{ "capability": "windowShade" }
],
"exclude": false
}
},
{
"type": "CAPABILITY",
"capabilityFilter": {
"capabilities": [
{ "capability": "doorControl" },
{ "capability": "multipleZonePresence" }
],
"exclude": false
}
}
]
}
This single subscription covers 22 capabilities across 3 filters — leaving 7 more filters available for expansion.
Using Event Type Filters for Broad Coverage
If you need events for more than 1,000 capabilities, or you want all events from a particular category regardless of capability, use event type filters instead:
{
"name": "All-Device-Events",
"sinkId": "your-sink-id",
"scope": "ACCOUNT",
"filters": [
{
"type": "EVENT_TYPE",
"eventTypeFilter": {
"eventTypes": [
{ "eventType": "DEVICE_EVENT" }
],
"exclude": false
}
}
]
}
This delivers all device events to your sink with a single filter — no need to enumerate capabilities individually. Use this approach when:
- You need comprehensive device telemetry
- Your back-end service filters events after receipt
- You're monitoring a diverse device fleet where new capabilities are added frequently
Best Practices
-
Start with event type filters if you need broad coverage. Only use capability filters when you need to reduce event volume to your webhook.
-
Group related capabilities into the same subscription for logical organization, even though filter evaluation is just OR logic.
-
Use separate sinks when events need to reach different back-end systems — don't route everything to one endpoint and re-dispatch internally if you can avoid it.
-
Reserve subscription slots for future growth. If you only need 5 subscriptions today, you have headroom for 5 more as your deployment expands.
-
Prefer fewer, broader subscriptions over many narrow ones. A single subscription with 10 capability filters (100 capabilities) is more quota-efficient than 10 subscriptions with 1 filter each.