Skip to content

Event types & payloads

Preview This is the catalog of events managed.dev emits. Every event shares one envelope; only the data payload differs by type. Subscribe an endpoint to the events you’ll act on, then verify and dedupe each delivery as described in the overview.

Every webhook body has the same outer shape. type selects the event, data carries the type-specific payload, and id is the unique delivery id you dedupe on. This is documented once here and not repeated per event below.

Common event envelope
{
"id": "evt_01J9...", // unique per delivery — dedupe on this
"type": "site.deployed", // selects the payload shape in data
"created_at": "2026-06-23T18:05:02.118Z",
"api_version": "2026-06-23",
"data": { /* type-specific payload, documented below */ },
"request_id": "req_01J9..."
}

Payloads are additive within an API version — ignore fields you don’t recognize rather than failing on them. The canonical, machine-readable list of every type lives in the event-types reference.

Event type Fires when Typical use
site.deployed A deployment finishes and an environment is serving a new release. Post a release note; warm caches; notify a channel.
deployment.failed A deployment can’t complete and the environment stays on its prior release. Page the on-call; surface the failure in CI.
build.succeeded A build produces a signed, content-addressed artifact ready to deploy. Trigger a promote; record the artifact id.
malware.detected A ClamAV scan finds and quarantines a hit. Open an incident; start your remediation runbook.
security.site_hacked Correlated signals indicate a site is compromised. Highest-priority alert; isolate and investigate.
job.succeeded An async job reaches succeeded. Close the loop on a long-running mutation without polling.
job.failed An async job reaches failed. Retry, roll back, or alert depending on the job type.
cert.renewed A TLS certificate is renewed for a hostname. Confirm coverage; refresh anything that pins the cert.
quota.exceeded A plan limit is hit (storage, sites, environments). Alert billing; clean up or upgrade before work blocks.

site.deployed reports the environment that updated and the release now serving. deployment.failed carries a reason and the failed_at stage so you can route the alert. build.succeeded gives you the artifact id to feed into a deploy.

site.deployed — data payload
{
"site_id": "site_01J7...",
"environment_id": "env_01J8...",
"environment": "production",
"deployment_id": "dep_01J8...",
"release_id": "rel_01J8...",
"branch": "main",
"commit": "9f3c1ab",
"artifact_id": "art_01J8...",
"deployed_at": "2026-06-23T18:05:01.992Z"
}
deployment.failed — data payload
{
"site_id": "site_01J7...",
"environment_id": "env_01J8...",
"environment": "staging",
"deployment_id": "dep_01J8...",
"branch": "feature/checkout",
"commit": "1c4d77e",
"failed_at": "build", // build | release | health-check
"reason": "composer install failed: package not found",
"job_id": "job_01J9...",
"failed_timestamp": "2026-06-23T18:04:42.118Z"
}

See deployments for the resources these events reference, and promote & rollback for the workflow behind them.

Job events mirror the job envelope. The payload tells you which job finished, what it acted on, and — on failure — the structured error.

job.succeeded — data payload
{
"job_id": "job_01J9...",
"type": "component.install",
"status": "succeeded",
"resource": {
"type": "component",
"kind": "plugin",
"slug": "wordpress-seo",
"site_id": "site_01J7...",
"environment_id": "env_01J8..."
},
"result": { "version": "24.1", "activated": true },
"finished_at": "2026-06-23T18:06:10.004Z"
}
job.failed — data payload
{
"job_id": "job_01J9...",
"type": "environment.refresh",
"status": "failed",
"resource": { "type": "environment", "id": "env_01J8...", "site_id": "site_01J7..." },
"error": {
"type": "conflict",
"code": "environment.refresh_in_progress",
"message": "a refresh is already running for this environment"
},
"failed_at": "2026-06-23T18:06:09.551Z"
}

Security events come from the security pipeline. malware.detected fires when a ClamAV scan quarantines a hit; security.site_hacked is the higher-order alert raised when correlated signals point to a compromise.

malware.detected — data payload
{
"site_id": "site_01J7...",
"environment_id": "env_01J8...",
"scan_id": "scan_01J9...",
"detections": [
{
"detection_id": "det_01J9...",
"path": "wp-content/uploads/2026/06/payload.php",
"signature": "PHP.Backdoor.Agent",
"action": "quarantined"
}
],
"detected_at": "2026-06-23T18:07:00.220Z"
}
security.site_hacked — data payload
{
"site_id": "site_01J7...",
"environment_id": "env_01J8...",
"indicators": ["malware.detected", "unexpected_admin_user", "blocks.spike"],
"severity": "critical",
"first_seen_at": "2026-06-23T18:06:30.000Z"
}

cert.renewed confirms a TLS certificate was reissued, with its new validity window. quota.exceeded fires when a plan limit is reached, naming the metric and where it stands.

cert.renewed — data payload
{
"site_id": "site_01J7...",
"certificate_id": "cert_01J8...",
"hostnames": ["example.com", "www.example.com"],
"issuer": "lets-encrypt",
"not_after": "2026-09-21T00:00:00Z",
"renewed_at": "2026-06-23T03:11:00.000Z"
}
quota.exceeded — data payload
{
"team_id": "team_01J...",
"metric": "storage", // storage | sites | environments
"limit": 25,
"unit": "GB",
"usage": 25.4,
"plan": "developer",
"exceeded_at": "2026-06-23T19:00:00.000Z"
}