Deploys
Record deploy markers and compute before/after behavior diffs around a deploy.
Deploy markers timestamp a release so you can see its before/after impact. There are two separate ways to create one, with different auth and different required fields — a CI-capture endpoint at the plain path, and a dashboard endpoint at the org/project-scoped path. Listing and diffing are only available org/project-scoped — there is no plain /api/deploys GET.
POST /api/deploys
Record a deploy marker from CI/CD. This is the only endpoint on this page at a plain (non-org-scoped) path.
Auth: API key (Bearer) — see Authentication
Request body
| field | type | required | description |
|---|---|---|---|
| service | string | yes | Service name |
| version | string | yes | Release version/tag |
| environment | string | no | e.g. production |
| git_sha | string | no | Commit SHA |
| source | string | no | Defaults to "ci" |
| external_id | string | no | Idempotency key — a repeat request with the same external_id (for this project) returns the original deploy instead of creating a duplicate |
| deployed_at | number | no | Epoch ms. Defaults to now; a future timestamp is clamped to now |
| metadata | object | no | Arbitrary JSON, stored alongside the deploy |
Response 201 (new deploy)
{ "id": "01hxyz...", "deployed_at": 1720392000000, "deduped": false }
Response 200 (idempotent replay — external_id matched an existing deploy)
{ "id": "01hxyz...", "deployed_at": 1720392000000, "deduped": true }
Errors:
400—{ "error": "service is required" }400—{ "error": "version is required" }
Common responses (401) apply — see Authentication. This endpoint does not enforce usage limits or rate limiting, so 402 and 429 don’t apply despite being API-key authenticated.
POST /api/orgs/:orgSlug/projects/:projectSlug/deploys
Record a deploy marker from the dashboard. Unlike the CI endpoint above, no fields are required — an empty body is valid.
Auth: session cookie (or API key, resolved to your account’s org/project membership) — see Authentication
Request body
| field | type | required | description |
|---|---|---|---|
| service | string | no | Service name |
| environment | string | no | e.g. production |
| version | string | no | Release version/tag |
| deployed_at | number | no | Epoch ms. Defaults to now |
source is always recorded as "dashboard" for this endpoint.
Response 201
{ "id": "01hxyz...", "deployed_at": 1720392000000 }
GET /api/orgs/:orgSlug/projects/:projectSlug/deploys
List the most recent deploy markers for the project. This endpoint has no plain /api/deploys path — it’s only mounted org/project-scoped.
Auth: session cookie (or API key, resolved to your account’s org/project membership)
Query params
| param | type | description |
|---|---|---|
| service | string | Exact match on service. Omit, or pass all, for no filter |
| environment | string | Exact match on environment. Omit, or pass all, for no filter |
Always returns at most 50 results, ordered by deployed_at descending (not configurable).
Response 200
{
"deploys": [
{
"id": "01hxyz...",
"project_id": "proj_01abc",
"service": "checkout-api",
"environment": "production",
"version": "v1.4.0",
"source": "dashboard",
"deployed_at": 1720392000000,
"created_at": 1720392000100
}
]
}
GET /api/orgs/:orgSlug/projects/:projectSlug/deploys/:id/diff
Compute a behavior diff for a deploy: event/error/warn counts and pattern frequency in the 15 minutes before vs. after deployed_at, plus newly-appearing patterns in the following hour.
Auth: session cookie (or API key, resolved to your account’s org/project membership)
Query params
| param | type | description |
|---|---|---|
| include_ai | string | Pass true to additionally attach an AI-generated natural-language summary_text. Best-effort — if AI generation errors, summary_text stays null rather than failing the request |
Response 200
{
"deploy": {
"id": "01hxyz...",
"version": "v1.4.0",
"service": "checkout-api",
"environment": "production",
"deployed_at": 1720392000000,
"source": "dashboard"
},
"window_before_minutes": 15,
"window_after_minutes": 15,
"pattern_window_hours": 1,
"new_patterns": [
{ "fingerprint": "fp_01hxyz", "message_template": "Timeout connecting to {service}", "level": "error", "first_seen_at": 1720392500000, "service": "checkout-api" }
],
"increased_patterns": [
{ "fingerprint": "fp_01abc", "message_template": "Retry attempt {n}", "level": "warn", "before": 4, "after": 22, "delta_pct": 4.5 }
],
"decreased_patterns": [],
"error_delta": 8,
"warn_delta": -2,
"total_events_before": 340,
"total_events_after": 402,
"top_impacted_services": [
{ "service": "checkout-api", "before": 120, "after": 180, "delta": 60 }
],
"summary_text": null
}
increased_patterns/decreased_patterns include only patterns whose frequency changed by at least 50% between the before/after hour buckets (capped at 10 each, sorted by magnitude of change). summary_text is null unless include_ai=true was passed and AI generation succeeded.
Errors: 404 — { "error": "not_found" } if the deploy ID doesn’t exist in this project
Common responses (401; 402 and 429 don’t apply to these endpoints) — see Authentication.