Authorization
Enterprise Eventing uses two distinct authorization mechanisms: Service Account tokens for making API requests to SmartThings, and HTTP Signatures for verifying webhook deliveries from SmartThings.
API Authentication
To create and manage sinks and subscriptions, your application authenticates using Service Account credentials.
Service Accounts
Service Accounts provide a way for your applications to authenticate with SmartThings APIs programmatically, without using a person's login credentials. See the Service Accounts documentation for complete details on:
Required Permissions
Access to Enterprise Eventing APIs is controlled by Service Account roles. Assigning the correct role to your Service Account grants the necessary OAuth scopes to your application.
For Account-level Sinks:
- Account Admin (
ACCOUNT_ADMIN
) - Required for creating and managing account-level sinks.
For Subscriptions:
- Account Admin (
ACCOUNT_ADMIN
) - Required for creating and managing account subscriptions.
Making API Requests
Include your Service Account's bearer token in the Authorization
header:
curl -X POST https://enterprise.smartthings.com/accounts/{accountId}/sinks \
-H 'Authorization: Bearer YOUR_SERVICE_ACCOUNT_TOKEN' \
-H 'Accept: application/vnd.smartthings+json;v=2' \
-H 'Content-Type: application/json' \
-d '{
"name": "My-Webhook-Endpoint",
"type": "HTTPS_SINK",
"httpsSink": {
"endpoint": "https://example.com/webhook"
}
}'
Sink Verification
When you create a sink, SmartThings sends a SINK_CONFIRMATION
challenge to your webhook endpoint to verify that you control the target URL. Your endpoint must respond with a 200 OK
and a JSON body containing the original challenge
value.
Example Challenge Request:
{
"accountId": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"notificationType": "SINK_CONFIRMATION",
"version": "2",
"sinkConfirmationNotification": {
"sinkId": "7de9a66a-8be6-4b69-9543-92ab3058bd6d",
"challenge": "550e8400-e29b-41d4-a716-446655440000"
}
}
Required 200 OK
Response:
{
"challenge": "550e8400-e29b-41d4-a716-446655440000"
}
If the challenge is not completed, the sink will not be activated, and no events will be delivered.
Webhook Signature Verification
When SmartThings delivers events to your webhook, the request is digitally signed using HTTP Signatures to prevent tampering and replay attacks.
Why Verify Signatures?
Although verifying signatures is optional, it's highly recommended to:
- Confirm the request originated from SmartThings
- Detect man-in-the-middle attacks
- Prevent replay attacks
- Verify the request body hasn't been tampered with
Signature Format
SmartThings signs webhook requests using the HTTP Signatures RFC specification. The signature appears in the Authorization
header:
Authorization: Signature
keyId="/pl/useast1/a1b2c3d4-e5f6-7890-1234-567890abcdef"
headers="(request-target) digest date"
algorithm="rsa-sha256"
signature="PS/XfElOxcA9PmD08l6Mr2Igporse8cqZKy+OKyRa4Basu/J7YetQdQnC/bV9bnd4WXV3..."
Signature Components
keyId
- URI path to retrieve SmartThings' public key for verificationheaders
- List of headers included in the signature (in order)algorithm
- Signing algorithm (rsa-sha256
)signature
- The actual signature to verify
Signed Headers
SmartThings signatures include these headers:
(request-target)
- Synthetic header combining HTTP method and URI path- Format:
post /your/webhook/path
(lowercase) - Not an actual HTTP header - computed for signing only
- Format:
digest
- SHA-256 digest of the request body- Verifies the body hasn't been modified
date
- Request timestamp- Prevents replay attacks (reject old signatures)
Retrieving the Public Key
SmartThings hosts public keys at:
https://key.smartthings.com/key/{keyId}
Append the keyId
from the signature to retrieve the RSA public key.
SmartThings public keys rotate regularly. To ensure your verification logic continues to work after a rotation, you must fetch keys dynamically using the keyId
from the signature.
For performance, it is recommended to cache the public keys. A good strategy is:
- Use the
keyId
as your cache key. - When a webhook arrives, check your cache for the
keyId
. - If the key is not in your cache (a cache miss), fetch it from
https://key.smartthings.com/key/{keyId}
and store it in your cache with a short Time-To-Live (TTL), such as a few hours.
Do not cache keys indefinitely. A short TTL ensures you will automatically pick up new keys after a rotation.
Verification Steps
- Parse the
Authorization
header to extract signature components - Fetch the public key from
https://key.smartthings.com/key/{keyId}
- Reconstruct the signing string from the specified headers
- Verify the signature using the public key
Example: Verification Pseudocode
function verifyWebhookSignature(request) {
// 1. Parse Authorization header
const signature = parseAuthorizationHeader(request.headers['authorization']);
// 2. Fetch SmartThings public key
const publicKey = fetchPublicKey(`https://key.smartthings.com/key/${signature.keyId}`);
// 3. Reconstruct signing string
const signingString = buildSigningString(request, signature.headers);
// 4. Verify signature
const isValid = verifyRSASignature(signingString, signature.signature, publicKey);
if (!isValid) {
throw new Error('Invalid signature');
}
// 5. Check date freshness (prevent replay attacks)
const requestDate = new Date(request.headers['date']);
const now = new Date();
const ageMinutes = (now - requestDate) / 1000 / 60;
if (ageMinutes > 5) {
throw new Error('Signature too old');
}
return true;
}
Security Best Practices
For API Requests
- Rotate API keys regularly - Generate new keys and disable old ones
- Secure token storage - Never commit tokens to version control
- Use HTTPS only - All API requests must use TLS
For Webhook Security
- Always use HTTPS - Webhooks must have valid SSL certificates
- Verify signatures - Implement signature verification to prevent attacks
- Validate request freshness - Reject signatures older than 5 minutes
- Be idempotent - Handle duplicate event deliveries gracefully
- Log security events - Track failed signature verifications
Rate Limiting and Retries
If your webhook endpoint fails to respond with a 2xx
status, SmartThings will automatically retry the delivery to handle transient network issues. Because retries can result in duplicate event deliveries, it is critical that your webhook is idempotent.
Ensure your webhook responds quickly (< 5 seconds) to avoid timeouts.
Troubleshooting
401 Unauthorized on API Requests
- Verify your Service Account token hasn't expired
- Confirm the Service Account has the required role assignments
- Check the
Accept
header includes the correct version (e.g.,application/vnd.smartthings+json;v=2
).
Webhook Signature Verification Failures
- Ensure you're fetching the public key dynamically (don't cache indefinitely)
- Verify the signing string matches exactly (including order of headers)
- Check that
(request-target)
is lowercase and properly formatted - Confirm the request
date
header is recent (< 5 minutes old)
Next Steps
- Review Event Types to understand webhook payloads
- See API Reference for complete API documentation
- Explore Service Accounts for detailed authentication setup