Skip to content

Incident.io Webhook

Route & Auth

Property Value
Method POST
Path /webhooks/incident/lead
Auth type svix
Headers webhook-signature, webhook-id, webhook-timestamp
Secret INCIDENT_WEBHOOK_SECRET
Service account incidentio-webhook@alan-eu-tools.iam.gserviceaccount.com
Response 204 No Content

Payload

Field Type Description
event_type string Event type
public_incident.incident_updated_v2 dict Incident details
incident_status string Current incident status (triage, live, post-mortem, etc.)
incident_role_assignments list[dict] Role assignments with assignee Slack user IDs
incident_id string Incident identifier

Behavior

  1. Skips incidents in triage or live status
  2. For other statuses, finds the "lead" role assignment
  3. Looks up the Alaner by Slack user ID
  4. Logs the lead assignment
  5. Checks if the alaner has the AlanToolsBackendIamManager role

Integrations

  • Incident.io: event source
  • Internal DB: alaner lookup by Slack ID

Code reference

apps.eu_tools.webhooks.incident.IncidentLeadBodySchema

Bases: Schema

data class-attribute instance-attribute

data = Dict(
    data_key="public_incident.incident_updated_v2",
    required=True,
)

event_type class-attribute instance-attribute

event_type = String(data_key='event_type', required=True)

apps.eu_tools.webhooks.incident.IncidentLeadWebhook

Bases: MethodView

post

post(payload)
Source code in apps/eu_tools/webhooks/incident.py
@incidentio_blueprint.arguments(IncidentLeadBodySchema, location="json")
@incidentio_blueprint.response(status_code=204)
def post(self, payload):  # type: ignore[no-untyped-def]
    if payload["data"].get("incident_status") in ["triage", "live"]:
        return

    for assignment in payload["data"].get("incident_role_assignments", []):
        if assignment["role"]["role_type"] == "lead" and assignment.get("assignee"):
            alaner = (
                current_session.execute(
                    select(Alaner).filter(
                        Alaner.slack_id == assignment["assignee"]["slack_user_id"]
                    )
                )
                .scalars()
                .unique()
                .one_or_none()
            )

            if alaner and not has_role(alaner, AlanToolsBackendIamManager):
                current_logger.info(
                    f"{alaner.email} is now incident lead for incident id: {payload['data'].get('incident_id')}"
                )

apps.eu_tools.webhooks.incident.incidentio_blueprint module-attribute

incidentio_blueprint = CustomBlueprint(
    "incident_webhook",
    "incident_webhook",
    url_prefix="/webhooks/incident",
    auth_context_providers=[
        WebhookAuthContextProvider(
            auth_type=svix,
            header_name="webhook-signature",
            secret_name_config_key="INCIDENT_WEBHOOK_SECRET",
            auth_principal_type=ServiceAccount,
            auth_principal_email="incidentio-webhook@alan-eu-tools.iam.gserviceaccount.com",
        )
    ],
)

OpenAPI

Incident.io webhook on ReDoc ⧉