Log streams send real-time webhook notifications to your endpoint when events occur in your Zapier account. You can use log streams to track Zap run success and failure rates, monitor configuration changes like new connections or Zap updates, build monitoring dashboards, and set up automated alerting.
Available on plans:
Free
Professional
Team
Enterprise
Prerequisites
- Enterprise plan.
- Super admin, or owner role.
- An HTTPS endpoint that can receive POST requests.
Available event types
Log streams support two categories of events:
- Asset management events: Track configuration changes such as Zaps created, connections updated, variables changed, and account membership updates.
- Execution log events: Track Zap run outcomes including success, error, and halted statuses.
Set up log streams as early as possible. Log streams only capture events that occur after creation, so you need to configure them on day one to build a complete history in your SIEM or monitoring software.
Asset management events
| Event | Description |
|---|---|
app_connection.created |
A user connected their app account to Zapier. |
app_connection.deleted |
A user deleted their app connection. |
app_connection.disconnected |
A connection expired and requires reconnection. |
app_connection.owner_changed |
A user transferred ownership of their app connection. |
app_connection.reconnected |
A user reconnected their app account to Zapier. |
app_connection.shared |
A user shared an app connection with other users. |
app_connection.unshared |
A user stopped sharing an app connection. |
| Event | Description |
|---|---|
variable.created |
A user created a new variable. |
variable.deleted |
A user deleted an existing variable. |
variable.owner_changed |
The owner changed for an existing variable. |
variable.updated |
A user edited an existing variable. |
| Event | Description |
|---|---|
mcp_server.created |
A user created a new MCP server. |
mcp_server.deleted |
A user deleted an MCP server. |
mcp_server.shared |
A user shared an MCP server with another user or account. |
mcp_server.sharing_role_updated |
A user changed sharing role permissions for a given user. |
mcp_server.tool_added |
A tool was added to an MCP server. |
mcp_server.tool_removed |
A tool was removed from an MCP server. |
mcp_server.tool_share_link_created |
A user created a new share link for their MCP server tool bundle. |
mcp_server.tool_share_link_deleted |
A user deleted a share link for their MCP server tool bundle. |
mcp_server.tool_updated |
A tool was updated on an MCP server. |
mcp_server.unshared |
A user unshared an MCP server with a user or account. |
mcp_server.updated |
A user updated an MCP server. |
| Event | Description |
|---|---|
table.created |
A user created a new table. |
table.deleted |
A user deleted their table. |
table.import_completed |
A table import finished. |
table.import_started |
A user began importing data into a table. |
table.shared |
A user shared a table with another user or account. |
table.sharing_role_updated |
A user changed sharing role permissions for a given user. |
table.unshared |
A user unshared a table with a user or account. |
| Event | Description |
|---|---|
account.member_added_to_account |
A new user was added to the account. |
account.member_invitation_accepted |
Someone accepted their member invitation and is now an active user of the account. |
account.member_invitation_sent |
An admin sent an invitation for a user to join the organization. |
account.member_logged_in |
A user in the account logged onto Zapier. |
account.member_permissions_updated |
A user's member permissions were changed. |
account.member_removed_from_account |
A user was removed from the account and no longer has access. |
| Event | Description |
|---|---|
zap.approval_request_approved |
A super admin or owner approved a change request. |
zap.approval_request_cancelled |
A user cancelled their change request. |
zap.approval_request_denied |
A super admin or owner denied a change request. |
zap.approval_request_sent |
A user submitted a change request for approval. |
zap.created |
A user created a new Zap. |
zap.moved_to_trash |
A user moved a Zap to the trash. |
zap.owner_changed |
A user transferred ownership of their Zap. |
zap.permanently_deleted |
A user permanently deleted a Zap. |
zap.restored_from_trash |
A user restored a Zap from the trash. |
zap.turned_off |
A user turned off a Zap. |
zap.version_enabled |
A user turned on a version of their Zap. |
zap.version_published |
A user published a new version of their Zap. |
Execution log events
| Event | Description |
|---|---|
zap_execution.error |
The Zap run failed due to an error. |
zap_execution.halted |
The Zap was automatically halted after repeated errors. |
zap_execution.success |
The Zap run completed with no errors. |
Create a log stream
- Go to the Admin Center by clicking the Admin Center icon in the left sidebar.
- In the admin settings sidebar, select Log streams under the Insights section.
- Click Create log stream.
- In the Name field, enter a descriptive name for your log stream (for example, "Production Error Alerts").
- In the Destination URL field, enter the HTTPS endpoint URL where you want to receive webhook notifications.
- (Optional) In the Secret field, click Generate to create a secure random secret, or enter your own secret (minimum 16 characters). Use this secret to verify webhook signatures.
- In the Events section, select the event types you want to receive notifications for.
- Click Save.
Your log stream is now active and will start sending webhook notifications when the selected events occur.
Manage log streams
After you create a log stream, it appears in the log streams list. The list displays each log stream's state, event count, and creation date.
You can take the following actions on a log stream:
- Edit: Update the name, destination URL, secret, or event selections.
- Pause: Temporarily stop webhook delivery without deleting the log stream.
- Delete: Permanently remove the log stream.
Event payload
When an event occurs, Zapier sends a JSON payload to your log stream's destination URL. The payload structure differs based on the event category.
Asset management events use a shared schema that tracks who performed an action, where it occurred, what was affected, and when it happened.
{
"event_id": "3564c9da-b3a5-43d3-b671-ef19f5eccf03",
"actor": {
"type": "user",
"id": "01009a9b-a5a4-85b4-b5a9-e94998489e2b"
},
"where": {
"id": "03d62d5d-26e7-87b2-a4c6-967869a8be1a",
"type": "account"
},
"when": {
"timestamp": "2025-08-26T09:52:50.625Z",
"timestamp_ms": 1756201970625
},
"what": {
"action": "zap.created",
"name": "Zap created"
},
"affected_object": {
"id": "00000000-0000-c000-8000-000293850453",
"type": "zap",
"name": "(Copy) mindesign webinar - 5 min before"
},
"context": {
"app_name": "Zoom",
"app_version": "2.25.0"
}
}
Change events
When an ownership change event occurs (such as zap.owner_changed, app_connection.owner_changed, or variable.owner_changed), the payload includes an additional what_changed object that describes the transition:
{
"actor": {
"id": "014ed0bb-cd81-82bc-a951-a00906b04e70",
"type": "user"
},
"where": {
"id": "0331f89b-ac40-8bdf-8ed8-af90110062d1",
"type": "account"
},
"what": {
"action": "zap.owner_changed",
"name": "Zap owner changed"
},
"affected_object": {
"id": "00000000-0000-c000-8000-000366644697",
"type": "zap",
"name": "Marketing AI Agent #1 — Customer feedback triage"
},
"what_changed": {
"change_type": "previous_value new_value",
"object": {
"previous_value": {
"id": "014ed0bb-cd81-82bc-a951-a00906b04e70",
"type": "user"
},
"new_value": {
"id": "015a0266-b8e0-89f6-b1ca-f20efd684448",
"type": "user"
}
},
"scalar": null
},
"context": {
"ip_address": "203.0.113.7"
},
"when": {
"timestamp": "2026-06-01T16:03:58.069Z",
"timestamp_ms": 1780329838069
}
}
| Field | Type | Description |
|---|---|---|
what_changed |
object | Describes what changed. Present for change events like ownership transfers. |
what_changed.change_type |
string | Type of change: object (structured data with id and type) or scalar (simple value). |
what_changed.object |
object or null | Contains previous_value and new_value when change_type is object. |
what_changed.object.previous_value |
object | The value before the change, containing id and type. |
what_changed.object.new_value |
object | The value after the change, containing id and type. |
what_changed.scalar |
object or null | Contains previous_value and new_value when change_type is scalar. |
context.ip_address |
string | IP address of the actor who performed the action. |
Payload fields
The following table describes each field in the asset management payload.
| Field | Type | Description |
|---|---|---|
event_id |
string | Unique identifier for the event. |
actor |
object | Who performed the action. |
actor.type |
string | Type of actor: user or system. |
actor.id |
string | Unique identifier for the actor. Present when actor.type is user. |
where |
object | Where the action occurred. |
where.id |
string | Account identifier. |
where.type |
string | Type of location (for example, account). |
when |
object | When the action occurred. |
when.timestamp |
string | ISO 8601 timestamp. |
when.timestamp_ms |
number | Unix timestamp in milliseconds. |
what |
object | What action was taken. |
what.action |
string | Event action name (for example, zap.created). |
what.name |
string | Human-readable event name. |
affected_object |
object | The object affected by the action. |
affected_object.id |
string | Unique identifier for the affected object. |
affected_object.type |
string | Object type (for example, zap, app_connection, variable). |
affected_object.name |
string | Name of the affected object. |
context |
object | Additional context. Varies by event type. |
Execution log events track Zap run outcomes including success, error, and halted statuses.
{
"version": "1.0.0",
"asset_type": "zap",
"asset_id": "123456",
"run_id": "abc-def-ghi-789",
"status": "success",
"started_at": "2025-01-15T10:30:00Z",
"error_message": null
}
Payload fields
The following table describes each field in the execution log payload.
| Field | Type | Description |
|---|---|---|
version |
string | Schema version (current: 1.0.0). |
asset_type |
string | Type of asset. Currently always zap. |
asset_id |
string | Unique identifier for the Zap. |
run_id |
string | Unique identifier for the specific Zap run. |
status |
string | Terminal status: success, error, or halted. |
started_at |
string | ISO 8601 timestamp when the Zap run started. |
error_message |
string or null | Error details when the Zap run fails. null for successful runs. |
Verify webhook signatures
When you create a log stream with a secret, Zapier signs each webhook request with an HMAC-SHA256 signature. Verify these signatures to confirm that incoming requests are from Zapier.
Each webhook request includes two headers:
| Header | Description |
|---|---|
X-Zapier-Signature |
HMAC-SHA256 signature, hex-encoded. |
X-Zapier-Timestamp |
Unix timestamp (in seconds) when the signature was generated. |
To verify the signature:
- Extract the signature and timestamp from the request headers.
- Construct the signed message by combining the timestamp and JSON body:
{timestamp}.{request_body}. - Compute the HMAC-SHA256 hash using your secret.
- Compare your computed signature with the
X-Zapier-Signatureheader value using a constant-time comparison function.
import hmac
import hashlib
def verify_webhook_signature(request_body, signature, timestamp, secret):
message = f"{timestamp}.{request_body}"
computed_signature = hmac.new(
key=secret.encode("utf-8"),
msg=message.encode("utf-8"),
digestmod=hashlib.sha256
).hexdigest()
return hmac.compare_digest(computed_signature, signature)
const crypto = require('crypto');
function verifyWebhookSignature(body, signature, timestamp, secret) {
const message = `${timestamp}.${body}`;
const computedSignature = crypto
.createHmac('sha256', secret).update(message).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(computedSignature));
}
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
)
func verifyWebhookSignature(body string, signature string, timestamp string, secret string) bool {
message := fmt.Sprintf("%s.%s", timestamp, body)
h := hmac.New(sha256.New, []byte(secret))
h.Write([]byte(message))
computedSignature := hex.EncodeToString(h.Sum(nil))
return hmac.Equal([]byte(signature), []byte(computedSignature))
}
Always use constant-time comparison functions (hmac.compare_digest() in Python, crypto.timingSafeEqual() in Node.js, hmac.Equal() in Go) to prevent timing attacks. Do not use standard string comparison operators.
Signature verification tips
- Use the raw request body. Do not parse and re-serialize the JSON. Formatting differences will cause verification to fail.
- UTF-8 encode all strings when computing the signature.
- Store your secret securely. Do not commit it to version control or expose it in client-side code.
Common use cases
- Error alerting: Get notified when Zap runs fail. Track error patterns and identify which Zap workflows need attention.
- Success rate metrics: Build dashboards showing Zap reliability over time. Calculate success rates and measure automation health.
- Automated recovery: Trigger workflows when Zap issues occur. For example, create support tickets when Zap workflows are halted, or start investigation workflows for persistent errors.
Troubleshooting
Webhook signature verification fails
- Verify you're using the raw request body string, not a parsed and re-serialized JSON object.
- Confirm all strings are UTF-8 encoded when computing the signature.
- Check that the timestamp value matches exactly what's in the
X-Zapier-Timestampheader. - Confirm you're using the same secret that was set when you created the log stream.
Webhook not received
- Verify your log stream is in an
activestate, notpaused. - Confirm you're subscribed to the event type you expect (for example,
zap_execution.error). - Verify your destination URL is correct and accessible from the internet.
- Confirm your destination URL uses HTTPS.
Limitations
- Log streams deliver events in real time, starting from when the log stream is created. Historical data is not available.