Ionhour Docs
Integrations

Deployments & Maintenance

Announce deploys and maintenance windows from your own CI so Ionhour pauses probing or suppresses alerts while you work — including a GitHub Actions example.

Two related endpoints let you tell Ionhour "we're changing something right now" from a customer's own pipeline. They behave differently, and the difference matters:

DeploymentMaintenance window
EffectAuto-pauses the associated checksSuppresses alerts and incidents
ProbingStops (paused checks are not probed)Continues (data keeps flowing)
Use whenA release restarts or briefly breaks a servicePlanned work where you still want data but no noise
Resourcemcp:deploymentsmcp:maintenance_windows

Both are workspace-scoped and self-healing: each has a TTL so an orphaned window (a pipeline that crashed before closing it) cleans itself up. All routes are under https://api.ionhour.com/api/v1.

Deployments

MethodPathMin rolePurpose
POST/v1/deploymentsmemberOpen a deployment window (pauses checks).
POST/v1/deployments/:id/endmemberClose it (resumes paused checks).
GET/v1/deploymentsviewerList deployments.

Open a deployment

POST /v1/deployments

FieldTypeRequiredNotes
projectIdnumberYesThe project being deployed. Must belong to the key's workspace.
namestringNoHuman label (max 255).
versionstringNoRelease/version string (max 255).
authorstringNoWho triggered it (max 255).
linkstringNoURL back to the CI run (max 2048).
checkIdsnumber[]NoSpecific checks to pause. Omitted → all checks in the project.
autoPausebooleanNoPause the checks for the window. Defaults to true.
ttlMinutesnumberNoServer-side auto-end, 1–1440 minutes from now. A fail-safe if /end never fires.

ttlMinutes is a safety net, not a schedule. The auto-end cron runs on a few-minute cadence, so a window ends around its TTL, not to the second. The explicit /end call is the precise close. Always send /end, and set a TTL so a failed pipeline still recovers.

curl -X POST https://api.ionhour.com/api/v1/deployments \
  -H "Authorization: Bearer ionh_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": 7,
    "version": "v1.4.2",
    "author": "ci-bot",
    "link": "https://github.com/acme/app/actions/runs/123",
    "autoPause": true,
    "ttlMinutes": 45
  }'

The response includes the deployment id, status (SCHEDULED, ACTIVE, or ENDED), and scheduledEndAt (set when you pass a TTL):

{
  "id": 910,
  "projectId": 7,
  "name": null,
  "version": "v1.4.2",
  "author": "ci-bot",
  "link": "https://github.com/acme/app/actions/runs/123",
  "status": "ACTIVE",
  "autoPause": true,
  "checkIds": null,
  "startedAt": "2026-07-10T14:00:00.000Z",
  "endedAt": null,
  "scheduledEndAt": "2026-07-10T14:45:00.000Z"
}

End a deployment

POST /v1/deployments/:id/end resumes the auto-paused checks. It is idempotent — ending an already-ended deployment returns 200 with its current state.

curl -X POST https://api.ionhour.com/api/v1/deployments/910/end \
  -H "Authorization: Bearer ionh_your_api_key"

List deployments

GET /v1/deployments accepts projectId, status, from, to, page, and limit, and returns the standard paginated envelope.

Maintenance windows

MethodPathMin rolePurpose
POST/v1/maintenance-windowsmemberOpen a maintenance window (suppresses alerts/incidents).
POST/v1/maintenance-windows/:id/endmemberEnd it early.
GET/v1/maintenance-windowsviewerList windows.

Open a window

POST /v1/maintenance-windows

FieldTypeRequiredNotes
namestringYesWindow label (max 255).
endAtISO-8601YesWhen the window ends — its natural TTL. A background processor auto-completes the window past endAt.
descriptionstringNoMax 2000 chars.
startAtISO-8601NoDefaults to now.
projectIdsnumber[]NoProjects covered. Omitted → all projects in the workspace. Every id must belong to the workspace.
suppressAlertsbooleanNoDefaults to true.
suppressIncidentsbooleanNoDefaults to true.
curl -X POST https://api.ionhour.com/api/v1/maintenance-windows \
  -H "Authorization: Bearer ionh_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "DB migration",
    "endAt": "2026-07-10T15:00:00.000Z",
    "projectIds": [7],
    "suppressAlerts": true,
    "suppressIncidents": true
  }'

The response includes the window id, state (SCHEDULED, ACTIVE, COMPLETED, or CANCELLED), and the resolved projectIds.

End a window

POST /v1/maintenance-windows/:id/end ends the window early (→ COMPLETED). Like deployments, it is idempotent — ending a window that is already in a terminal state returns its current state.

Because endAt is a TTL, a window closes on its own even if this call never fires — the natural self-healing path for a crashed pipeline.

List windows

GET /v1/maintenance-windows accepts state, projectId, from, to, page, and limit, and returns the standard paginated envelope.

Example: wrap a deploy in GitHub Actions

This generic workflow opens a deployment window before the release and closes it afterward. The close step uses if: always() so it runs even when the deploy fails, and the ttlMinutes / endAt TTLs guarantee cleanup even if the whole runner dies. Store your key as the IONHOUR_API_KEY secret.

name: deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      IONHOUR_API_KEY: ${{ secrets.IONHOUR_API_KEY }}
      IONHOUR_BASE: https://api.ionhour.com/api/v1
      IONHOUR_PROJECT_ID: '7'
    steps:
      - name: Open Ionhour deployment window
        id: ionhour_open
        run: |
          DEPLOY_ID=$(curl -sS -X POST "$IONHOUR_BASE/deployments" \
            -H "Authorization: Bearer $IONHOUR_API_KEY" \
            -H "Content-Type: application/json" \
            -d "{
              \"projectId\": $IONHOUR_PROJECT_ID,
              \"version\": \"${GITHUB_SHA::7}\",
              \"author\": \"$GITHUB_ACTOR\",
              \"link\": \"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\",
              \"autoPause\": true,
              \"ttlMinutes\": 45
            }" | jq -r '.id')
          echo "deploy_id=$DEPLOY_ID" >> "$GITHUB_OUTPUT"

      - name: Deploy
        run: ./scripts/deploy.sh

      - name: Close Ionhour deployment window
        if: always() && steps.ionhour_open.outputs.deploy_id != ''
        run: |
          curl -sS -X POST \
            "$IONHOUR_BASE/deployments/${{ steps.ionhour_open.outputs.deploy_id }}/end" \
            -H "Authorization: Bearer $IONHOUR_API_KEY"

Swap /deployments for /maintenance-windows (with an endAt instead of ttlMinutes) when you want probing to keep running and only the alerting suppressed — for example, a schema migration where you still want latency data but no pages.