Skip to main content

Webhook Logs

Tags: integrations, logging, webhooks

Webhook request history and debugging

Resources​

Request and response models used by the endpoints on this page.

DataRecordResponse​

FieldTypeRequiredDescription
accessModeInteger
createdAtDateTime✓
dataTypeIdInteger✓
externalIdString
fieldValuesDict[str, Any]✓
idInteger✓
memberIdInteger✓
memberNameString
retirementDataRecordRetirementResponse | null
updatedAtDateTime✓
uuidUUID✓

Example:

{
"id": 0,
"uuid": "00000000-0000-0000-0000-000000000000",
"dataTypeId": 0,
"memberId": 0,
"fieldValues": {},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}

DataRecordRetirementResponse​

FieldTypeRequiredDescription
reasonLiteral['monday_item_archived', 'monday_item_deleted']✓
sourceLiteral['monday']Default: monday
statusLiteral['retired']Default: retired

Example:

{
"status": "retired",
"reason": "monday_item_archived",
"source": "monday"
}

EventRuleResponse​

FieldTypeRequiredDescription
actionParamsDict[str, Any]✓
actionSetLockedBooleanDefault: False
actionType<enum EventRuleActionType✓
activeBoolean✓
appConnectionIdInteger
calendarEventTypeIdInteger✓
calendarIdInteger✓
celBlockedAtDateTime
conditionsString✓
createdAtDateTime✓
dataTypeIdInteger✓
dataTypeNameString
delayInteger✓
errorString✓
errorMessageString✓
eventType<enum EventRuleEventType✓
failedAtDateTime✓
idInteger✓
journeyIdInteger
journeyStepIdInteger✓
nameString✓
objectType<enum EventRuleObjectType✓
orderInteger✓
routineIdInteger✓
taskIdInteger✓
taskNameString
taskWorkflowIdInteger
triggerParamsDict[str, Any]✓
updatedAtDateTime✓
uuidString✓
workflowRevisionIdInteger✓

Example:

{
"id": 0,
"uuid": "string",
"objectType": null,
"name": "string",
"eventType": null,
"conditions": "string",
"actionType": null,
"actionParams": {},
"triggerParams": {},
"active": false,
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z",
"taskId": 0,
"dataTypeId": 0,
"routineId": 0,
"workflowRevisionId": 0,
"calendarId": 0,
"calendarEventTypeId": 0,
"journeyStepId": 0,
"error": "string",
"errorMessage": "string",
"failedAt": "2024-01-01T00:00:00Z",
"delay": 0,
"order": 0,
"actionSetLocked": false
}

PaginatedResponse[WebhookLogResponse]​

FieldTypeRequiredDescription
itemsArray<WebhookLogResponse>✓
pageInteger✓
pageSizeInteger✓
totalInteger✓
totalPagesInteger✓

Example:

{
"items": [],
"total": 0,
"page": 0,
"pageSize": 0,
"totalPages": 0
}

WebhookLogReplayResponse​

FieldTypeRequiredDescription
eventIdString✓
replayOfIdInteger✓
ruleIdInteger✓
statusLiteral['queued']✓
workflowIdString✓

Example:

{
"status": "queued",
"replayOfId": 0,
"ruleId": 0,
"eventId": "string",
"workflowId": "string"
}

WebhookLogResponse​

FieldTypeRequiredDescription
createdAtDateTime✓
dispatchKeyString
errorMessageString
eventTypeString✓
idInteger✓
memberIdInteger
recordDataRecordResponse | null
recordIdInteger
replayOfIdInteger
replayableBooleanDefault: False
ruleEventRuleResponse | null
ruleIdInteger
statusCodeInteger
successBoolean✓
urlString✓

Example:

{
"id": 0,
"url": "string",
"eventType": "string",
"success": false,
"createdAt": "2024-01-01T00:00:00Z",
"replayable": false
}

WorkspaceOrgEndpointResponse​

FieldTypeRequiredDescription
destinationDigestString✓First 12 hex characters of SHA-256 over the full URL
destinationHostString✓scheme://host[:port] of the endpoint URL — never the path or query
eventTypesArray✓
limitedToWorkspacesBoolean✓
nameString✓
organizationIdInteger✓
statusString✓
uuidString✓Endpoint uuid (org-side identifier)

Example:

{
"uuid": "string",
"name": "string",
"destinationHost": "string",
"destinationDigest": "string",
"status": "string",
"eventTypes": [],
"limitedToWorkspaces": false,
"organizationId": 0
}

Endpoints​

List​

GET /api/v2/w/{workspace_uuid}/webhook-logs

Description:

List all webhook logs for the workspace with pagination.

PHI-classified despite returning no payload body: errorMessage carries the receiver's response text, which routinely echoes the delivered payload back (see _send_webhook_request — the body is kept here for the operator precisely because it is too sensitive for application logs). A page of failed deliveries is therefore a PHI read, and a paged scrape of it is bulk access.

Authorization: Requires webhooks:read scope

Parameters:

  • page (Integer) — min: 1
  • pageSize (Integer) — min: 1, max: 100
  • sortBy (WebhookLogSortField)
  • sortOrder (SortOrder)
  • eventType (EventRuleEventType)
  • success (Boolean)

Response: See PaginatedResponse[WebhookLogResponse]


Org Endpoints​

GET /api/v2/w/{workspace_uuid}/webhook-logs/org-endpoints

Description:

Workspace-side visibility for org webhooks (GRA-8314 §5).

The org webhook's inclusion rule is decided at configuration time by an org admin (audited there); this read is (b)'s visibility half — any member holding webhooks:read (the workspace's webhook-read scope, which workspace admins hold) can see that their workspace feeds an org endpoint, with IDs and the endpoint's public shape only. Never a secret, never delivery contents, never the full URL. An endpoint that does not cover this workspace is deliberately absent: listing it would disclose org configuration this workspace is not party to.

One indexed query: an endpoint covers this workspace when the operator explicitly selected the whole organization or linked this workspace — the same rule the fan-out applies, expressed in SQL over the link table.

Authorization: Requires webhooks:read scope

Response: List of WorkspaceOrgEndpointResponse


Replay​

POST /api/v2/w/{workspace_uuid}/webhook-logs/{log_id}/replay

Description:

Re-send a previously delivered webhook payload.

The stored body is re-sent verbatim — same eventId, so a receiver that deduplicates on it sees the same event rather than a new one — signed with the rule's CURRENT secret and a FRESH timestamp, and posted to the destination the payload was originally delivered to (WebhookLog.url), which the rule must still point at. See replay_eligibility for why the destination is pinned to the log rather than resolved from the rule: read at replay time it would let anyone who can edit a rule redirect a thousand stored PHI bodies to a new endpoint, correctly signed.

Replay is therefore useful after a receiver outage or a secret rotation, and deliberately NOT after a URL correction — that case is indistinguishable from the attack, and its recovery is to re-drive the event from the source records.

WEBHOOKS_WRITE rather than WEBHOOKS_READ: replay causes an outbound delivery to a third party. It is a write in the only sense that matters here, even though it changes nothing in the workspace.

Audit: this emits BOTH a config-change event (an operator acted on automation configuration) and PHI_RECORD_EXPORTED (PHI was disclosed to an external party — the §164.312(b) "record export ... destination" row). The disclosure event is emitted here, at authorization, because this is where the actor is known; the transmission outcome is the WebhookLog row the delivery activity writes, correlated by dispatchKey. A replay that is queued and never delivered therefore still records as an authorized disclosure — over-recording, which is the correct direction for a disclosure trail.

Responses:

  • 404 — no such log in this workspace.
  • 409 — the log has no stored payload (written before this feature, or the attempt failed before a payload was built), or the originating EventRule is gone, inactive, has no webhook URL, or now points somewhere other than where this delivery went. None of those become true by retrying.
  • 422 — no JSON body. An empty {} is required; see WebhookLogReplayRequest.
  • 429 — replay budget exhausted.

Authorization: Requires webhooks:write scope

Parameters:

  • log_id (Integer)
  • _body (WebhookLogReplayRequest)

Response: See WebhookLogReplayResponse